一道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 相关文章推荐
JavaScript下利用fso判断文件是否存在的代码
Dec 11 Javascript
关于JavaScript中name的意义冲突示例介绍
May 29 Javascript
Javascript表单特效之十大常用原理性样例代码大总结
Jul 12 Javascript
百度地图JavascriptApi Marker平滑移动及车头指向行径方向
Mar 13 Javascript
vue.js获得当前元素的文字信息方法
Mar 09 Javascript
微信小程序websocket实现聊天功能
Mar 30 Javascript
详解如何在nuxt中添加proxyTable代理
Aug 10 Javascript
angular4强制刷新视图的方法
Oct 09 Javascript
vue实现分页组件
Jun 16 Javascript
JavaScript常用内置对象用法分析
Jul 09 Javascript
node静态服务器实现静态读取文件或文件夹
Dec 03 Javascript
Handtrack.js库实现实时监测手部运动(推荐)
Feb 08 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数组应用之比较两个时间的相减排序
2008/08/18 PHP
完美解决PHP中文乱码
2009/11/26 PHP
php 自写函数代码 获取关键字 去超链接
2010/02/08 PHP
第七章 php自定义函数实现代码
2011/12/30 PHP
php实现格式化多行文本为Js可用格式
2015/04/15 PHP
thinkphp3.2.0 setInc方法 源码全面解析
2018/01/29 PHP
JS 巧妙获取剪贴板数据 Excel数据的粘贴
2009/07/09 Javascript
Mootools 1.2教程 输入过滤第一部分(数字)
2009/09/15 Javascript
js/jquery判断浏览器的方法小结
2014/09/02 Javascript
前端轻量级MVC框架CanJS详解
2014/09/26 Javascript
JQuery分屏指示器图片轮换效果实例
2015/05/21 Javascript
浅谈JavaScript中的对象及Promise对象的实现
2015/11/15 Javascript
JavaScript模版引擎的基本实现方法浅析
2016/02/15 Javascript
深入理解在JS中通过四种设置事件处理程序的方法
2017/03/02 Javascript
浅谈React Native Flexbox布局(小结)
2018/01/08 Javascript
AngularJS双向数据绑定原理之$watch、$apply和$digest的应用
2018/01/30 Javascript
vue-cli2打包前和打包后的css前缀不一致的问题解决
2018/08/24 Javascript
微信小程序制作表格的方法
2019/02/14 Javascript
[43:41]OG vs Newbee 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
[46:42]DOTA2-DPC中国联赛正赛 Aster vs Magma BO3 第二场 3月5日
2021/03/11 DOTA
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
2014/06/10 Python
python音频处理用到的操作的示例代码
2017/10/27 Python
Python语言快速上手学习方法
2018/12/14 Python
Python3.5面向对象程序设计之类的继承和多态详解
2019/04/24 Python
python读取raw binary图片并提取统计信息的实例
2020/01/09 Python
使用Python matplotlib作图时,设置横纵坐标轴数值以百分比(%)显示
2020/05/16 Python
Python利用Pillow(PIL)库实现验证码图片的全过程
2020/10/04 Python
西班牙在线宠物商店:zooplus.es
2017/02/24 全球购物
北京SQL新华信咨询
2016/09/30 面试题
教师批评与自我批评范文
2014/10/15 职场文书
工作失误检讨书范文
2015/01/26 职场文书
交流会主持词
2015/07/02 职场文书
会议简讯范文
2015/07/20 职场文书
2019年让高校“心动”的自荐信
2019/03/25 职场文书
导游词之沈阳植物园
2019/11/30 职场文书
JS精髓原型链继承及构造函数继承问题纠正
2022/06/16 Javascript