要想完全明白JavaScript的閉包,要先明白js中的一些基礎(chǔ)原理,然后我再給出一些例子來講解閉包。
在執(zhí)行JavaScript時會創(chuàng)建一個執(zhí)行環(huán)境(excution context),執(zhí)行環(huán)境定義了變量或函數(shù)可以訪問的其他數(shù)據(jù)。每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象(variable object 有些地方叫域?qū)ο?Scope object)),在執(zhí)行環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。雖然我們編寫的代碼無法訪問這個對象,但解析器在處理數(shù)據(jù)時會在后臺使用它。
全局執(zhí)行環(huán)境是最外層的一個執(zhí)行環(huán)境。根據(jù)js實(shí)現(xiàn)的宿主環(huán)境的不同,環(huán)境對象不一樣。瀏覽器中,全局執(zhí)行環(huán)境是window,node.js的全局變量是global,所有的全局變量和方法都保存在全局對象中。
每個函數(shù)都有自己的執(zhí)行環(huán)境。當(dāng)調(diào)用進(jìn)入一個函數(shù)時,函數(shù)的執(zhí)行環(huán)境就會被創(chuàng)建。代碼在執(zhí)行環(huán)境中運(yùn)行時,他創(chuàng)建用于保存變量對象的作用域鏈(scope chain)。他的作用是保存一個執(zhí)行環(huán)境所有可以訪問的變量或函數(shù)的有序集合。作用域的最前面是當(dāng)前執(zhí)行的代碼所在執(zhí)行環(huán)境的變量對象。如果當(dāng)前的執(zhí)行環(huán)境是一個函數(shù),就將函數(shù)的活動對象作為變量對象,剛開始時只有一個變量arguments。作用域鏈中的下一個變量對象是包含當(dāng)前環(huán)境變量的外部環(huán)境也就是他的調(diào)用者,再下一個是更外層的,至到全局執(zhí)行環(huán)境。
所以在一個執(zhí)行中的方法內(nèi)訪問一個不存在于這個執(zhí)行環(huán)境中的變量時不會報錯,解析器會從作用域鏈的頂端的變量對象開始找,如果找不到就找下一個執(zhí)行環(huán)境的變量對象,一直到全局環(huán)境變量。如果有則停止查找。如果找到全局變量對象還是沒有發(fā)現(xiàn),就會報錯。
簡單說就是,一個函數(shù)體內(nèi)就是一個執(zhí)行環(huán)境,當(dāng)一個函數(shù)在執(zhí)行時,會創(chuàng)建一個作用鏈,這個鏈中有自己的變量對象,同時也有外層的變量對象。
示例1:全局執(zhí)行環(huán)境
網(wǎng)友評論