写出执行以下代码的结果:
function fun(n, o) {
console.log(o);
return {
fun: function (m) {
return fun(m, n);
}
};
}
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);
代码运行的过程,在以下代码中:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>闭包堆栈的小题</title>
</head>
<body>
<script>
function fun(n, o) {
console.log(o);
return {
fun: function (m) {
return fun(m, n);
}
};
}
var c = fun(0).fun(1);
c.fun(2);
c.fun(3); //=> undefined 0 1 1
// 输出结果为:undefined 0 1 1,执行过程如下:
/*
ECSTack:
EC(G):
VO(G):
Fun ,创建一个变量fun,并且创建一个堆,并将这个堆赋值给Fun,Fun = AAAFFF000。
var c = fun(0).fun(1); =>先创建变量c,然后执行fun(0),而后将结果.fun(1)执行,最后将这个结果赋值给变量c。执行结果如下:
因为是函数,所以会创建有一个新的执行上下文,称为EC(FUN)1,也就是fun(0),里面的内容为:
变量对象:AO(FUN)1;作用域链为:<--,VO(G)>
传递的实参个数,arguments=1
形参赋值:
n = 0,
o = undefined
代码执行:
console.log(o) =>undefined
return {fun:function(m){return fun(m,n)}},在此返回一个对象,创建一个新的堆对象,名为AAAFFF111,fun(0)执行后,要执行"结果.fun(1)",即AAAFFF111.fun(1),会产生一个新的执行上下文,anonymous是匿名的意思,可以称上下文为EC(AM)1,里面的内容为:
创建变量对象AO(AM)1 ; 作用域链<AO(AM)1,AO(FUN)1>
传递的实参个数,arguments=1
形参赋值:m=1
代码执行:return fun(m,n),m是1,而n本作用域没有,向上级找,在AO(FUN)1
中,n为0,=>所以是return fun(1,0),先执行fun(1,0).然后将这个的函数结果返回,故创建新的上下文,再一次执行fun():
EC(FUN)2:=> fun(1,0)
创建变量:AO(FUN)2;作用域链:<AO(FUN)2,VO(G)>,上级作用域链是找在哪里创建的,Fun是在全局创建的所以,是VO(G)
传递的实参个数,arguments=2
形参赋值:
n:1,
o:0
代码执行:
console.log(o)=>0
return {
fun:function(){...}
},返回一个对象,在此是将这个返回的结果给c,所以这个return对象就是c,因是在AO(FUN)2中创建的,上级作用域就是AO(FUN)2。
c.fun(2);=>执行c中的fun函数,会创建新的执行上下文,EC(AM)2,传个2 => AM(2):
创建变量对象AO(AM)2;作用域链:<AO(AM)2,AO(FUN)2>
传递的实参个数:arguments=1;
形参赋值:m=2;
代码往下执行:
return fun(m,n)=> m是2,n在本作用域中没有,向上级查找,就是AO(FUN)2中,n=1,即return fun(2,1),要执行fun(2,1),然后将执行结果返回,所以就是fun()第三次执行,会形成新的执行上下文,即EC(FUN)3: => fun(2,1)
里面的执行:
创建新的变量对象AO(FUN)3;作用域链为<AO(FUN)3,VO(G)>因为fun是在全局创建,所以上级为VO(G)。
fun(2,1) => 因为在上述代码中直接return fun(m,n),即fun(2,1),接下来就是执行fun(2,1):
传递的实参个数为:arguments=2
形参赋值:
n:2,
o:1
代码执行:
console.log(o) =>1
return{
fun:function(){...}
}
c.fun(3)=>执行c中的fun函数,会创建新的执行上下文,EC(AM)3,传个3 => AM(3):
创建变量对象AO(AM)3;作用域链:<AO(AM)3,AO(FUN)2>
传递的实参个数:arguments=1;
形参赋值:m=3;
代码往下执行:
return fun(m,n)=> m是3,n在本作用域中没有,向上级查找,就是AO(FUN)2中,n=1,即return fun(3,1),要执行fun(3,1),然后将执行结果返回,所以就是fun()再次执行,会形成新的执行上下文,即EC(FUN)4: => fun(3,1)
里面的执行:
创建新的变量对象AO(FUN)4;作用域链为<AO(FUN)4,VO(G)>因为fun是在全局创建,所以上级为VO(G)。
fun(3,1) => 因为在上述代码中直接return fun(m,n),即fun(2,1),接下来就是执行fun(3,1):
传递的实参个数为:arguments=2
形参赋值:
n:3,
o:1
代码执行:
console.log(o) =>1
return{
fun:function(){...}
}
*/
</script>
</body>
</html>
如下图: