关于闭包的一个问题

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的输出分别是什么?

阅读 3k
4 个回答

首先看第一句:var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
a = fun(0)给函数fun传递了第一个参数n,第二个参数o为undefined,所以console.log(o)为undefined。然后函数给a返回了属性fun。
a.fun(1)调用了a的属性fun,传递了第一个参数m,然后调用了函数fun,参数为m,n并返回调用结果。此时m=1,而因为闭包,n的值保留了下来,并作为了调用的函数fun的参数n。所以此时a.fun(1)实际上是return fun(1,0);所以console.log(o)输出值为0;
a.fun(2)和a.fun(3)同理。

第二句:var b = fun(0).fun(1).fun(2).fun(3);
fun(0)此时参数n=0,输出undefined并返回了一个属性,这是属性是fun函数,该fun函数只有一个参数m,

fun(1)即调用该fun函数属性,该属性调用了一个新的fun函数,并返回它的值。该fun函数的参数为m,n,此时m=1,n=0;所以输出0;而它返回的值又返回了一个新的fun属性,此时n=1,o=0;

fun(2)即调用该fun函数属性,该属性调用了一个新的fun函数,并返回它的值。该fun函数的参数为m,n,此时m=2,n=1;所以输出1;而它返回的值又返回了一个新的fun属性,此时n=2,o=1;

fun(3)即调用该fun函数属性,该属性调用了一个新的fun函数,并返回它的值。该fun函数的参数为m,n,此时m=3,n=2;所以输出2;而它返回的值又返回了一个新的fun属性,此时n=3,o=2;

第三句:var c = fun(0).fun(1); c.fun(2); c.fun(3);
c = fun(0).fun(1)输出undefined和0,此时n=1,返回了一个属性,这是属性是fun函数,有一个参数m;
c.fun(2)调用了该属性,此时m=2,该属性返回了一个名为fun的函数的值,这个fun函数的两个参数m=2,n=1,所以输出了1;
c.fun(3)调用了该属性,此时m=3,该属性返回了一个名为fun的函数的值,这个fun函数的两个参数m=3,n=1,所以还是输出了1;

emmm说了这么一大堆绕口令,希望对你有帮助。

链式调用和直接调用的区别搞懂这个就懂原理了, 至于答案, 比较绕而已

上面的回答很详细了,
我简短的说下。不对之处请指教

第一行 返回的闭包a保存的 n=0 o=undefined ,所以在调用return fun(m,n) 里n永远等于保存的0.

第二行 由于是链式调用,会导致闭包不断更新 其内部的n,o会保存上一次调用的值

第三行 是第一行+第二行组合版

所以我认为关键在于闭包有没有被替换或者说更新,如果不更新,怎么调用其实闭包所引用的值都是不会变化的

如图,第一行:undefined,0,0,0
第二行:undefined,0,1,2
第三行:undefined,0,1,1
clipboard.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题