一道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脚本性能的优化方法
Feb 02 Javascript
javascript数组使用调用方法汇总
Dec 08 Javascript
JS 图片缩放效果代码
Jun 09 Javascript
jQuery标签替换函数replaceWith()的使用例子
Aug 28 Javascript
javascript实现相同事件名称,不同命名空间的调用方法
Jun 26 Javascript
js clearInterval()方法的定义和用法
Nov 11 Javascript
详解Js模板引擎(TrimPath)
Nov 22 Javascript
jQuery中页面返回顶部的方法总结
Dec 30 Javascript
实例详解JSON取值(key是中文或者数字)方式
Aug 24 Javascript
分分钟学会vue中vuex的应用(入门教程)
Sep 14 Javascript
详解如何用模块化的方式写vuejs
Dec 16 Javascript
使用Layui搭建后台管理界面的操作方法
Sep 20 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扩展vld查看PHP opcode操作步骤
2013/03/04 PHP
PHP实现的下载远程图片自定义函数分享
2015/01/28 PHP
thinkPHP引入类的方法详解
2016/12/08 PHP
老生常谈PHP面向对象之命令模式(必看篇)
2017/05/24 PHP
yii2多图上传组件的使用教程
2018/05/10 PHP
TP5.0框架实现无限极回复功能的方法分析
2019/05/04 PHP
PHP设计模式之迭代器模式Iterator实例分析【对象行为型】
2020/04/26 PHP
一个符号插入器 中用到的js代码
2007/09/04 Javascript
详解JavaScript对W3C DOM模版的支持情况
2015/06/16 Javascript
JQuery标签页效果的两个实例讲解(4)
2015/09/17 Javascript
AngularJS 表达式详细讲解及实例代码
2016/07/26 Javascript
AngularJS  ng-repeat遍历输出的用法
2017/06/19 Javascript
详解webpack异步加载业务模块
2017/06/23 Javascript
js中如何完美的解析数据
2018/03/18 Javascript
利用nodeJs anywhere搭建本地服务器环境的方法
2018/05/12 NodeJs
JavaScript HTML DOM元素 节点操作汇总
2019/07/29 Javascript
vue实现文字加密功能
2019/09/27 Javascript
Python列表切片用法示例
2017/04/19 Python
今天 平安夜 Python 送你一顶圣诞帽 @微信官方
2017/12/25 Python
PyCharm 设置SciView工具窗口的方法
2019/01/15 Python
用python打印1~20的整数实例讲解
2019/07/01 Python
Python 点击指定位置验证码破解的实现代码
2019/09/11 Python
tensorflow 利用expand_dims和squeeze扩展和压缩tensor维度方式
2020/02/07 Python
python 安装教程之Pycharm安装及配置字体主题,换行,自动更新
2020/03/13 Python
利用CSS3实现动态的二级三级菜单效果实例源码
2017/01/04 HTML / CSS
HTML5的结构和语义(3):语义性的块级元素
2008/10/17 HTML / CSS
英国第一的购买便宜玩具和游戏的在线购物网站:Bargain Max
2018/01/24 全球购物
瑞士图书网站:Weltbild.ch
2019/09/17 全球购物
美国波西米亚风格精品店:South Moon Under
2019/10/26 全球购物
大学生入党思想汇报
2014/01/01 职场文书
观看信仰心得体会
2014/09/04 职场文书
《月球之谜》教学反思
2016/02/20 职场文书
解决Go gorm踩过的坑
2021/04/30 Golang
浅谈golang 中time.After释放的问题
2021/05/05 Golang
css实现两栏布局,左侧固定宽,右侧自适应的多种方法
2021/08/07 HTML / CSS
Android开发手册TextInputLayout样式使用示例
2022/06/10 Java/Android