深入理解JavaScript作用域、变量对象、闭包

来源:互联网 发布:软件系统概述 编辑:程序博客网 时间:2024/06/06 11:39

几个月前用到了js,想深入理解js,汤姆大叔http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html是个好东西,可惜第一遍看的时候津津有味,感觉懂了,几个月没用js就记不得细节了,翻来覆去看了几遍,钻深了以后总感觉有不会的地方。做一个记录,有想法就记下来。

在知乎下写过一点

先举个例子,说明为什么要用闭包
var data = [];
for (var k = 0; k < 3; k++) {
data[k] = function () {
alert(k);
};
}
data[0](); // 3, 而不是0
data[1](); // 3, 而不是1
data[2](); // 3, 而不是2

一目明了,使用闭包之后

var data = [];
for (var k = 0; k < 3; k++) {
data[k] = (function _helper(x) {
return function () {
alert(x);
};
})(k); // 传入"k"值
}
// 现在结果是正确的了
data[0](); // 0
data[1](); // 1
data[2](); // 2
这个例子可以回答'什么样的需求下才需要闭包?
浏览本问题的应该都是像我一样的js小白,都体会过面对晦涩文字的沮丧,所以写的时候尽量通俗易懂,做入门之用。
要搞明白闭包,先要弄清楚闭包的七大姑八大姨——作用域链(scope chain)、变量对象(variable object)、执行环境(execution contexts)。
var x = 10;
function foo() {
alert(x);
}
(function () {
var x = 20;
foo(); // 10, but not 20
})();
即使20小兄弟离foo这么近,在一个括号里面,foo()还是10?
到底是为什么呢?这就要讲到变量对象和执行环境。
在上面这个例子中:
foo()是一个申明,(function(){})是一个表达式,(function(){})()是表示自运行函数;
全局上下文的变量对象是:
globalContext.VO === Global = {
  x: 10  foo: <reference to function>};在“foo”创建时,“foo”的[[scope]]属性是:foo.[[Scope]] = [  globalContext.VO];在“foo”激活时(匿名函数调用),“foo”上下文的活动对象是:fooContext.AO = {没有};“foo”上下文的作用域链为:fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.: fooContext.Scope = [  fooContext.AO,  globalContext.VO];x=20不会出现在foo的作用域链;这个例子也清晰的表明,一个函数(这个例子中为从函数“foo”返回的匿名函数)【我认为应该是从匿名函数返回的“foo”函数】的[[scope]]持续存在,即使是在函数创建的作用域已经完成之后。接下来就要分析data[k]()这个例子的作用域链了,我还没搞明白

0 0
原创粉丝点击