一道JS前端闭包面试题解析


Posted in Javascript onDecember 25, 2015

问题

代码A

function fun(n,o){
  console.log(o);
  return {
    fun:function(m){//[2]
      return fun(m,n);//[1]
    }
  }
}

var a=fun(0);
a.fun(1);
a.fun(2);
a.fun(3);
var b=fun(0).fun(1).fun(2).fun(3);
var c=fun(0).fun(1);
c.fun(2);
c.fun(3);

求出程序输出

这是一个闭包测试题

转换为等价代码

return返回的对象的fun属性对应一个新建的函数对象,这个函数对象将形成一个闭包作用域,使其能够访问外层函数的变量n及外层函数fun,为了不将fun函数和fun属性搞混,我们将上述代码修改如下:
代码B

function _fun_(n,o){
  console.log(o);
  return {
    fun:function(m){
      return _fun_(m,n);
    }
  }
}

var a=_fun_(0);//undefined
a.fun(1);//0
a.fun(2);//0
a.fun(3);//0

var b=_fun_(0).fun(1).fun(2).fun(3);
//undefined,0,1,2

var c=fun(0).fun(1);//undefined,0,
c.fun(2);//1
c.fun(3); //1

那么就有同学问了,为什么可以这样改呢,你怎么能确定[1]处的fun不是[2]代码所在处的fun呢,要知道此处的fun属性可是指向一个函数对象哦~
这里就要说到JS的词法作用域,JS变量作用域存在于函数体中即函数体,并且变量的作用域是在函数定义声明的时候就是确定的,而非在函数运行时。
如下代码

var name="global";
function foo(){
  console.log(name);
}

function fooOuter1(){
  var name="local";
  foo();
}
fooOuter1();//输出global 而不是local,并且和闭包没有任何关系

function fooOuter2(){
  var name="local";
  function foo(){
    console.log(name);
  }
  foo();
}
fooOuter2();//输出local 而不是global,在函数声明是name变量作用域就在其外层函数中,嗯嗯就是闭包~

好了我们回到题目,在函数声明定义阶段,[2]处的匿名函数进行定义声明,发现在[1]处需要引用一个名为fun的函数对象,那么首先在当前函数体内寻找,发现没有,那么就到其外层函数-这个匿名函数的包裹函数中去查找,发现也没有,到外层函数中去,发现外面没有函数包裹了,那就到全局环境下去找,额偶终于找到了......就把fun函数指定为全局环境下的fun函数对象并加入到匿名函数的闭包中去。至此我们就知道代码B为什么和代码A是等价的了~~~

创建闭包作用域

JS在词法分析结束后,确定了1个闭包,就是返回的对象fun属性对应的匿名函数的闭包-访问全局环境下的_func_及其外层函数的函数内部变量n;
在每次_func_执行的时候,都会将闭包中变量的作用域信息传递到函数执行环境中,供函数执行时获取变量值时使用

执行输出

var a=_fun_(0);//undefined
a.fun(1);//0
a.fun(2);//0
a.fun(3);//0

_fun_函数执行,因为第2个参数未定义,输出undefined。然后返回一个对象,带有fun属性,指向一个函数对象-带有闭包,能够访问到_fun_和变量n_
a.fun(1)执行返回的对象的fun方法,传入m的值1,调用返回_fun_(1,0)
所以输出为0,a.fun(2),a.fun(3)和a.fun(1)

var b=_fun_(0).fun(1).fun(2).fun(3);
等价代码:

var b=_fun_(0);
var b1=b.fun(1);
var b2=b1.fun(2);//[3]
var b3=b2.fun(3);//[4]
前2句和上面的输出相同undefined,0,当[3]被调用时,b1对象中有一个闭包,引用了_fun_函数及外层函数变量n=1,所以匿名函数执行的函数调用为_fun_(2,1),输出结果为1,并返回一个新的对象。
当[4]执行时,b2对象也有一个闭包,引用了_fun_函数及外层函数变量n=2,执行_fun_(3,2),输出结果为2

var c=fun(0).fun(1);//undefined,0,
c.fun(2);//1
c.fun(3); //1

能看懂前面的代码执行解释,理解上面的代码执行输出就不会有问题了,希望大家喜欢。

Javascript 相关文章推荐
自制轻量级仿jQuery.boxy对话框插件代码
Oct 26 Javascript
Egret引擎开发指南之运行项目
Sep 03 Javascript
Javascript学习笔记之数组的构造函数
Nov 23 Javascript
Jquery全屏相册插件zoomvisualizer具有调节放大与缩小功能
Nov 02 Javascript
谈谈js中的prototype及prototype属性解释和常用方法
Nov 25 Javascript
基于HTML模板和JSON数据的JavaScript交互(移动端)
Apr 06 Javascript
详解Vuex中mapState的具体用法
Sep 28 Javascript
vue按需引入element Transfer 穿梭框
Sep 30 Javascript
微信小程序实现横向滚动导航栏效果
Dec 12 Javascript
微信小程序实现页面浮动导航
Jan 08 Javascript
Angular处理未可知异常错误的方法详解
Jan 17 Javascript
JavaScript中isPrototypeOf函数
Nov 07 Javascript
干货分享:让你分分钟学会javascript闭包
Dec 25 #Javascript
javascript生成img标签的3种实现方法(对象、方法、html)
Dec 25 #Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
Dec 25 #Javascript
JavaScript中Window对象的属性及事件
Dec 25 #Javascript
JavaScript字符串删除重复字符的方法
Dec 25 #Javascript
JavaScript如何实现在文本框(密码框)输入提示语
Dec 25 #Javascript
jquery实现图片预加载
Dec 25 #Javascript
You might like
php array_keys 返回数组的键名
2016/10/25 PHP
PHPstorm激活码2020年5月13日亲测有效
2020/09/17 PHP
用javascript将数据库中的TEXT类型数据动态赋值到TEXTAREA中
2007/04/20 Javascript
Jquery Uploadify上传带进度条的简单实例
2014/02/12 Javascript
node.js中的fs.readdir方法使用说明
2014/12/17 Javascript
JavaScript判断表单提交时哪个radio按钮被选中的方法
2015/03/21 Javascript
详解iframe与frame的区别
2016/01/13 Javascript
jQuery xml字符串的解析、读取及查找方法
2016/03/01 Javascript
js+css实现select的美化效果
2016/03/24 Javascript
angular项目中bootstrap-datetimepicker时间插件的使用示例
2018/03/15 Javascript
JavaScript解决浮点数计算不准确问题的方法分析
2018/07/09 Javascript
[54:54]Newbee vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python文件去除注释的方法
2015/05/25 Python
Python部署web开发程序的几种方法
2017/05/05 Python
浅谈Python实现2种文件复制的方法
2018/01/19 Python
pygame游戏之旅 计算游戏中躲过的障碍数量
2018/11/20 Python
对python读取CT医学图像的实例详解
2019/01/24 Python
python自动发微信监控报警
2019/09/06 Python
tensorflow 实现打印pb模型的所有节点
2020/01/23 Python
python+gdal+遥感图像拼接(mosaic)的实例
2020/03/10 Python
Python字符串查找基本操作代码案例
2020/10/27 Python
在Python中字典按值排序的实现方法
2020/11/12 Python
美国花布包包品牌:Vera Bradley
2017/08/11 全球购物
英国赛车、汽车改装和摩托车零件购物网站:Demon Tweeks
2018/10/29 全球购物
情人节活动策划方案
2014/02/27 职场文书
家长写给老师的建议书
2014/03/13 职场文书
团日活动总结报告
2014/06/25 职场文书
食品质量与安全专业毕业生求职信
2014/08/11 职场文书
推广活动策划方案
2014/08/23 职场文书
庆祝儿童节标语
2014/10/09 职场文书
离婚协议书范本及离婚须知
2014/10/15 职场文书
玩手机检讨书1000字
2014/10/20 职场文书
2014年个人总结范文
2015/03/09 职场文书
2016年小学生寒假家长评语
2015/10/10 职场文书
七年级作文之游记
2019/12/11 职场文书
redis 存储对象的方法对比分析
2021/08/02 Redis