一道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 FormatNumber函数实现方法
Dec 30 Javascript
Mootools 1.2教程 类(一)
Sep 15 Javascript
HTML上传控件取消选择
Mar 06 Javascript
js模仿jquery的写法示例代码
Jun 16 Javascript
JavaScript中使用数组方法汇总
Feb 16 Javascript
servlet+jquery实现文件上传进度条示例代码
Jan 25 Javascript
js上传图片预览的实现方法
May 09 Javascript
vue插件mescroll.js实现移动端上拉加载和下拉刷新
Mar 07 Javascript
《javascript设计模式》学习笔记五:Javascript面向对象程序设计工厂模式实例分析
Apr 08 Javascript
vue使用map代替Aarry数组循环遍历的方法
Apr 30 Javascript
微信小程序之滑动页面隐藏和显示组件功能的实现代码
Jun 19 Javascript
简单聊聊TypeScript只读修饰符
Apr 06 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的知识
2006/11/17 PHP
PHP开发中常用的字符串操作函数
2011/02/08 PHP
基于PHP对XML的操作详解
2013/06/07 PHP
PHP根据IP判断地区名信息的示例代码
2014/03/03 PHP
使用php方法curl抓取AJAX异步内容思路分析及代码分享
2014/08/25 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
js资料prototype 属性
2007/03/13 Javascript
jQuery 图像裁剪插件Jcrop的简单使用
2009/05/22 Javascript
javascript 显示当前系统时间代码
2009/12/28 Javascript
node.js中的fs.createWriteStream方法使用说明
2014/12/17 Javascript
JS实现滑动菜单效果代码(包括Tab,选项卡,横向等效果)
2015/09/24 Javascript
JS基于面向对象实现的拖拽库实例
2015/09/24 Javascript
Zero Clipboard实现浏览器复制到剪贴板的方法(多个复制按钮)
2016/03/24 Javascript
jQuery弹出下拉列表插件(实现kindeditor的@功能)
2016/08/16 Javascript
Three.js获取鼠标点击的三维坐标示例代码
2017/03/24 Javascript
jQuery插件artDialog.js使用与关闭方法示例
2017/10/09 jQuery
详解bootstrap导航栏.nav与.navbar区别
2017/11/23 Javascript
Nuxt.js踩坑总结分享
2018/01/18 Javascript
[02:41]2015国际邀请赛中国区预选赛观战指南
2015/05/20 DOTA
详解Python命令行解析工具Argparse
2016/04/20 Python
使用pandas对两个dataframe进行join的实例
2018/06/08 Python
python中使用psutil查看内存占用的情况
2018/06/11 Python
Django ORM 常用字段与不常用字段汇总
2019/08/09 Python
python 队列基本定义与使用方法【初始化、赋值、判断等】
2019/10/24 Python
Python笔记之facade模式
2019/11/20 Python
pytorch 图像中的数据预处理和批标准化实例
2020/01/15 Python
使用Numpy对特征中的异常值进行替换及条件替换方式
2020/06/08 Python
10行Python代码实现Web自动化管控的示例代码
2020/08/14 Python
用CSS3来实现社交分享按钮
2014/11/11 HTML / CSS
课例研修方案
2014/05/31 职场文书
信息管理专业自荐书
2014/06/05 职场文书
谢师宴邀请函
2015/02/02 职场文书
外出考察学习心得体会
2016/01/18 职场文书
《比的意义》教学反思
2016/02/18 职场文书
幼儿园中班教学反思
2016/03/03 职场文书
MySQL系列之七 MySQL存储引擎
2021/07/02 MySQL