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,?,?,?
分析第一题
全局预编译
GO{
fun:function(n,o){...}
a:undefined
}
全局预编译开始执行代码
遇到 fun(0)
走函数预编译
AO1{
n:0, //预编译第三步实参形参统一将m为0赋值给n
o:undefined
}
预编译完成
开始执行 var a = fun(0);
代码都是从左到右执行的 先 var a 然后 fun(0) 然后赋值 var a = fun(0)
然后我么开始执行 fun(0)
打印console.log(o) o此时是什么状况呢? console.log一个变量 这个变量是哪里来的?
很显然 o 在AO对象里面是undefined
然后函数接着执行
函数执行结束 执行 var a = fun(0); 那么此时的全局的GO对象变化
GO{
fun: function(n, o) {... }
a: {
fun: function (m) {
return fun(m, n);
}
}
}
接着执行
a.fun(1) // 此时a是Go里的变量a
a: {
fun: function (m) {
return fun(m, n);
}
}
接着函数调用 执行预编译
生成AO对象
AO1{
n:1, //m传过来的
o:0 //n传过来的
}
AO2{
m: 1 //这是形参实参统一 a.fun(1) 传过来的 1
// n: 0, // 这里没有n 会往上找 n继承AO1行n 就是0
}
第一题 最里面的AO没有n他是拿到的外面AO的n 一直没有变化 所以是0
结果是 undefined 0 0 0
分析第二题
第二题前两个步骤是一样的,所以也是fun(0).fun(1)也是 undefined 和 0
关键是第三步这里 fun(0).fun(1).fun(2)
上一步骤的参数n会通过递归套娃的方式传递给下一个参数o
而且每次调用都会生成新的AO
AO1{
n:2,
o:1
}
AO2{
m:2,
//n: 2 自始至终AO2的n都是没有的
}
第四步这里 fun(0).fun(1).fun(2).fun(3)
AO1{
n:3
o:2
}
AO2{
m:3,
}
总结一下
var b = fun(0).fun(1).fun(2).fun(3);
(第一步) fun(0) 产生AO1 返回了AO2
(第二步) fun(0).fun(1) 也会产生AO1 返回了AO2 (第一步返回的AO2)拿到(第一步)的AO1的引用作为(第二步)的AO1的初始化
以此类推 第三步会拿到第二步的AO2
注意每次函数执行前的预编译生成的AO都是独立的存在,逻辑上AO是互相引用,实际上每次函数执行都是独立的