一道闭包题题解

2016-01-02 20:58:00  浏览:1684  作者:管理员

题目来自 大部分人都会做错的经典JS闭包面试题。

很有意思的题目,切一发。

function fun(n,o) {  console.log(o)  return {    fun:function(m){      return fun(m,n);    }  };}var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?//问:三行a,b,c的输出分别是什么?

先看第一组执行,fun(0) 后首先打印 undefined,没有问题。之后变量 a 便被赋值为 fun 函数所 return 的对象。即:

a = {  fun: function(m) {    return fun(m, n);  }};

这里要重点注意的是参数 n,值为 0,这就是闭包和作用域链。

接着执行 a.fun(1) a.fun(2) a.fun(3),我们以 a.fun(1) 举例。a.fun(1) 的执行结果,因为没有赋值(其实有个 return value),所以其实就是执行了一遍 fun(m, n),上面说了,n 值为 0,所以控制台输出为 0。后两个输出同理。这里要注意的就是这个 n,因为作用域链,所以 n 能获取值,为 0,因为 n 被变量 a 所引用,所以它一直贮藏在内存中。

再来看第二组,我们可以把它改成这样。

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

第一行,打印 undefined,没有问题,a 返回对象,然后执行 a.fun(1),打印 0,这些跟第一次的执行相同。a.fun(1),其实就是执行 fun(m, n),其实就是 fun(1, 0),return 的对象赋值给 b。

var b = {  fun: function(m) {    return fun(m, n); // n=1  }};

类似的结果,唯一不同的是 n 的值变了,这是由 fun() 传入的参数所决定的。

接下去,b.fun(2),执行 fun(2, 1),打印出 1,然后将 return 的对象赋值给 c。

var c = {  fun: function(m) {    return fun(m, n); // n=2  }};

最后一步也是类似,所以依次打印 undefined, 0, 1, 2。

最后看第三组。由第二组可得变量 c 的结果:

var c = {  fun: function(m) {    return fun(m, n); // n=1  }};

然后执行过程和 1 类似,就不用多说了。

综:个人认为这道题的 "恶心" 之处多数在于函数中调用函数本身(fun 函数中调用 fun 函数),而引起的思路混乱,其他部分其实跟下面代码类似,归根结底就是被引用的变量会始终存在在内存中。

function fn() {  var num = 0;  return function() {    console.log(num++);  }}var a = fn();a();  // 0a();  // 1var b = fn();b();  // 0b();  // 1

更多精彩分析可以参考原文。

评论区

共 0 条评论
  • 这篇文章还没有收到评论,赶紧来抢沙发吧~

【随机新闻】

返回顶部