1

1
2
3
4
5
6
7
8
9
10
11
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);

输出:
undefined 0 0 0
undefined 0 1 2
undefined 0 1 1
闭包位置在 function(m),它的作用域在第一层函数 fun。

  1. 关于变量a的思路
    var a = fun(0);这里先创建了属于a的作用域,然后调用的是第一层函数 fun,并且参数 n=0,o=undefined,console.log(o) 输出 undefined,返回属性 fun。
    a.fun(1);此时调用的是fun(0)的返回值第二层函数 fun,即调用 function(m),并且将参数 m 赋值为1,根据函数内容继续调用第一层函数 fun,因为 function(m)的作用域在第一层函数,所以它保存了参数 n=0,console.log(o) 输出的值是0,返回属性 fun。
    a.fun(2);此时调用的还是fun(0)的返回值第二层函数 fun,不关 a.fun(1) 的事。
    a.fun(3);这个情况和前两句语句一样。
  2. 关于变量b的思路
    var b = fun(0).fun(1).fun(2).fun(3);这里先创建了属于b的作用域,然后第一个 fun(0)调用的是第一层函数 fun,并且参数 n=0,o=undefined,console.log(o) 输出 undefined,返回属性 fun。
    第二个 fun(1)使用了上一个 fun(0)的返回属性 fun,调用了第二层函数 fun,参数 m=1,n=0,然后接着调用第一层函数 fun,此时 o=0,console.log(o) 输出0,返回属性 fun。
    第三个 fun(2)使用了上一个 fun(1)的返回属性 fun,调用了第二层函数 fun,参数 m=2,n=1,然后接着调用第一层函数 fun,此时 o=1,console.log(o) 输出1,返回属性 fun。
    第四个同理。
  3. 关于变量c的思路
    var c = fun(0).fun(1); 这里先创建了属于b的作用域,然后第一个 fun(0)调用的是第一层函数 fun,并且参数 n=0,o=undefined,console.log(o) 输出 undefined,返回属性 fun。第二个 fun(1)使用了上一个 fun(0)的返回属性 fun,调用了第二层函数 fun,参数 m=1,n=0,然后接着调用第一层函数 fun,此时 o=0,console.log(o) 输出0,返回属性 fun。
    c.fun(2);此时调用的是上一句c.fun(0),fun(1)的第二个属性fun(1)的返回属性 fun,此时的参数 m=2,n=1,因此调用第一层函数输出1。

2

1
2
3
4
5
6
7
8
9
10
11
12
13
function counter(){
var count = 0;
return function(){
return count++;
}
}
var abc = counter();
var xyz = counter();
abc();//0
abc();//1
abc();//2
xyz();//0
xyz();//1

闭包位置在匿名函数,它的作用域在函数 counter()。
var abc = counter();//这里先创建了属于 abc 的作用域,该语句执行完以后 abc 的作用域拥有了变量 count,并且得到 a = function(){return count++;},开始执行第一个语句 abc()时,此时是 abc()=count++; 并且 abc 作用域里已经有变量 count ,所以 count = 1,结果是0(这里考到++的前后位置的用法),开始执行第二个语句 abc()时,此时还是 abc()=count++; 还是继续调用 abc 作用域的变量 count,count = 2,结果是1。