一道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 相关文章推荐
动态调用css文件——jquery的应用
Feb 20 Javascript
JS定义回车事件(实现代码)
Jul 08 Javascript
JS把内容动态插入到DIV的实现方法
Jul 19 Javascript
html+js+highcharts绘制圆饼图表的简单实例
Aug 04 Javascript
BootStrap无限级分类(无限极分类封装版)
Aug 26 Javascript
JS实现动态添加DOM节点和事件的方法示例
Apr 28 Javascript
微信小程序switch开关选择器使用详解
Jan 31 Javascript
Vue.js特性Scoped Slots的浅析
Feb 20 Javascript
socket在egg中的使用实例代码详解
May 30 Javascript
vue 解决form表单提交但不跳转页面的问题
Oct 30 Javascript
使用js实现单链解决前端队列问题的方法
Feb 03 Javascript
基于Cesium绘制抛物弧线
Nov 18 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中设置时区方法小结
2012/06/03 PHP
Drupal7连接多个数据库及常见问题解决
2014/03/02 PHP
PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
2014/07/23 PHP
深入剖析浏览器退出之后php还会继续执行么
2016/05/17 PHP
PHP实现的服务器一致性hash分布算法示例
2018/08/09 PHP
基于jQuery的简单九宫格实现代码
2012/08/09 Javascript
jQuery:节点(插入,复制,替换,删除)操作
2013/03/04 Javascript
js无刷新操作table的行和列
2014/03/27 Javascript
coffeescript使用的方式汇总
2015/08/05 Javascript
js实现向右横向滑出的二级菜单效果
2015/08/27 Javascript
浅谈Express异步进化史
2017/09/09 Javascript
JavaScript中的函数申明、函数表达式、箭头函数
2019/12/06 Javascript
微信小程序语音同步智能识别的实现案例代码解析
2020/05/29 Javascript
如何在面试中手写出javascript节流和防抖函数
2020/10/22 Javascript
pandas多级分组实现排序的方法
2018/04/20 Python
python3处理含有中文的url方法
2018/05/10 Python
使用Python AIML搭建聊天机器人的方法示例
2018/07/09 Python
对Tensorflow中的变量初始化函数详解
2018/07/27 Python
Python爬虫之pandas基本安装与使用方法示例
2018/08/08 Python
Python的几种主动结束程序方式
2019/11/22 Python
Python基于Dlib的人脸识别系统的实现
2020/02/26 Python
python3用PyPDF2解析pdf文件,用正则匹配数据方式
2020/05/12 Python
Django 允许局域网中的机器访问你的主机操作
2020/05/13 Python
使用CSS3来实现滚动视差效果的教程
2015/08/24 HTML / CSS
Europcar美国/加拿大:预订汽车或卡车租赁服务
2018/11/13 全球购物
幼儿教师自我鉴定
2013/11/02 职场文书
电厂厂长岗位职责
2014/01/02 职场文书
元旦促销方案
2014/03/15 职场文书
考生诚信考试承诺书
2014/05/23 职场文书
相亲大会策划方案
2014/06/05 职场文书
党支部创先争优活动总结
2014/08/28 职场文书
镇党委书记群众路线整改措施思想汇报
2014/10/13 职场文书
就业意向协议书
2015/01/29 职场文书
毕业论文致谢词
2015/05/14 职场文书
安全知识竞赛主持词
2015/06/30 职场文书
探究Mysql模糊查询是否区分大小写
2021/06/11 MySQL