关于闭包的一些题目(一)

今天看见一道自认为比较有难度比较绕的闭包题目,倒腾了好一会才弄出答案来,这题目是别人博客里面写的,本着“自己懂还不算真的懂,给别人讲懂了才算真的懂的原则”,故我在这篇博客里面来说说这道题目

这是本人第一次描述这些题目,如果有用词不当,请提出^_^
原作者的链接我会赋到最下面,如有冒犯请通知我,我会删掉的。

题目如下

1
2
3
4
5
6
7
8
9
10
11
12
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);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2); c.fun(3);
//问:三行a,b,c的输出分别是什么?

是不是有点懵逼?如果是,请先冷静一下哈,太懵逼是没办法解决问题的(虽然我看到第一眼就懵了,但是你可以慢慢来,还是可以梳理好的)。如果不是那你一定在闭包上面有深深的理解。

第一个 fun 函数,是标准具名函数声明,返回了一个对象字面量表达式,也就是一个 object
第二个 fun 是一个属性,是匿名函数表达式。
第三个 fun 是调用的,也就是第一个fun,有点递归的意思。这里或许你会问为什么不等于第二个 fun ?其实我们可以将以下代码在浏览器console测试一下
假如是第三个fun是同第二个一样:

1
2
3
4
5
6
var o={
fn:function (){
console.log(fn);
}
};
o.fn();//ERROR报错

我们发现它最终会报错,显示fn is not defined(...)
下面再看另一个

1
2
3
4
var fn = function (){
console.log(fn);
};
fn();//function (){console.log(fn);};正确

这次就没有报错了,var 在函数外部创建了一个fn,函数内部找不到fn则可以向上寻找,但是第一种是在函数内部创建的,没办法找到。

所以我们可以得知,第三个函数是第一个的这个fun
所以我们回顾一下原来的函数

1.第一行

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

首先fun(0),即n = 0传入了fun(n,o),此时o没有值,则为undefined :
故第一个输出为 undefined
接着的return返回了一个对象字面量表达式,也就是类似下面

1
2
3
4
5
var a = {
fun:function(m){
return fun(m,n);
}
}

接着的 a.fun(1) 参数 m = 1 , n的值我们之前在fun(0)里面知道了——是 0。则下面的fun(m,n)则是 fun(1,0) ,再倒回去看函数第一个fun(最外面的那个)m->nn->o,所以打印出来的o也就是最后n的值,为 0

那么 a.fun(2)呢?其实也是差不多的,m = 2的时候,n还是原来的 n = 0,你问为什么?因为在var a = fun(0)的时候已经确定了呢,所以最终输出 0(第三个fun的参数n将值赋给了第一个funo)

所以这么看来的话,第一行的第三个是不是也是很好解决呢?
和前面两个一样也是等于0

所以第一行的答案是:
undefined 0 0 0

2.第二行

1
var b = fun(0).fun(1).fun(2).fun(3);
  1. 首先第一个值是undefined是同刚刚第一行的一样的。
  2. 那么接下来看又引用了 fun这个方法,也就是m = 1,n是原来的0,也就是最后o = 0,那么第二个输出的数字就为 0
  3. 此时还没完呢,接着又马上来了个fun(2),此时的fun其实又变成了最外层的那个fun,那么m = 2,n = 1,对应fun(n,o)就是 n=2,o=1.此刻你应该明白了,下一个输出的数是 1
  4. 最后一个是fun(3),这个又再次变成了fun里面的那个方法fun里面的函数,由于上次 n=2 m=3 => fun(3,2),最后一个输出 2

所以第二行的答案是:
undefined 0 1 2

3.第三行

1
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);
  1. 由于前面两个在第二行里面是类似的,这边就直接跳过了,输出undefined 和0
  2. 这时候,c.fun(2) => fun(m,n) => m = 2, n在上一个已经等于1, 也就是在fun(n,o)里面n =2,o = 1;
    所以此次输出 1
  3. 第三个 c.fun(3) => fun(m,n) => m=3,n=1。所以最后在函数 fun(n,o)n=3,o = 1,所以还是输出1

所以第三行的答案是:
undefined 0 1 1

原作者博客连接

IT程序狮

# js, 闭包

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×