深入理解JavaScript作用域、變量對象、閉包

幾個月前用到了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]()這個例子的作用域鏈了,我還沒搞明白

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章