游戏租号网站怎么建设,舆情报告总结,精准营销英文,wordpress google js前面的话 本文从执行环境的角度来分析闭包#xff0c;先用一张图开宗明义#xff0c;然后根据图示内容对代码进行逐行说明#xff0c;试图对闭包进行更直观的解释 图示 说明 下面按照代码执行流的顺序对该图示进行详细说明 function foo(){var a 2;function bar(){console.…前面的话 本文从执行环境的角度来分析闭包先用一张图开宗明义然后根据图示内容对代码进行逐行说明试图对闭包进行更直观的解释 图示 说明 下面按照代码执行流的顺序对该图示进行详细说明 function foo(){var a 2;function bar(){console.log(a);}return bar;
}
var baz foo();
baz(); 【1】代码执行流进入全局执行环境并对全局执行环境中的代码进行声明提升(hoisting) 【2】执行流执行第9行代码var baz foo();调用foo()函数此时执行流进入foo()函数执行环境中对该执行环境中的代码进行声明提升过程。此时执行环境栈中存在两个执行环境foo()函数为当前执行流所在执行环境 【3】执行流执行第2行代码var a 2;对a进行LHS查询给a赋值2 【4】执行流执行第7行代码return bar;将bar()函数作为返回值返回。按理说这时foo()函数已经执行完毕应该销毁其执行环境等待垃圾回收。但因为其返回值是bar函数。bar函数中存在自由变量a需要通过作用域链到foo()函数的执行环境中找到变量a的值所以虽然foo函数的执行环境被销毁了但其变量对象不能被销毁只是从活动状态变成非活动状态而全局执行环境的变量对象则变成活动状态执行流继续执行第9行代码var baz foo();把foo()函数的返回值bar函数赋值给baz 【5】执行流执行第10行代码baz();通过在全局执行环境中查找baz的值baz保存着foo()函数的返回值bar。所以这时执行baz()会调用bar()函数此时执行流进入bar()函数执行环境中对该执行环境中的代码进行声明提升过程。此时执行环境栈中存在三个执行环境bar()函数为当前执行流所在执行环境 在声明提升的过程中由于a是个自由变量需要通过bar()函数的作用域链bar() - foo() - 全局作用域进行查找最终在foo()函数中也就是代码第2行找到var a 2;然后在foo()函数的执行环境中找到a的值是2所以给a赋值2 【6】执行流执行第5行代码console.log(a);调用内部对象console并从console对象中log方法将a作为参数传递进入。从bar()函数的执行环境中找到a的值是2所以最终在控制台显示2 【7】执行流执行第6行代码}bar()的执行环境被弹出执行环境栈并被销毁等待垃圾回收控制权交还给全局执行环境 【8】当页面关闭时所有的执行环境都被销毁 总结 从上述说明的第5步可以看出由于闭包bar()函数的原因虽然foo()函数的执行环境销毁了但其变量对象一直存在于内存中就是为了能够使得调用bar()函数时可以通过作用域链访问到父函数foo()并得到其变量对象中储存的变量值。直到页面关闭foo()函数的变量对象才会和全局的变量对象一起被销毁从而释放内存空间 由于闭包占用内存空间所以要谨慎使用闭包。尽量在使用完闭包后及时解除引用以便更早释放内存 //通过将baz置为null解除引用
function foo(){var a 2;function bar(){console.log(a);//2}return bar;
}
var baz foo();
baz();
baz null;
/*后续代码*/