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