什么是作用域鏈泛啸?
我的理解就是铝量,根據(jù)在內(nèi)部函數(shù)可以訪問外部函數(shù)變量的這種機(jī)制,用鏈?zhǔn)讲檎覜Q定哪些數(shù)據(jù)能被內(nèi)部函數(shù)訪問茬末。
想要知道js怎么鏈?zhǔn)讲檎页ч唬偷孟攘私鈐s的執(zhí)行環(huán)境
每個函數(shù)運(yùn)行時都會產(chǎn)生一個執(zhí)行環(huán)境,而這個執(zhí)行環(huán)境怎么表示呢丽惭?js為每一個執(zhí)行環(huán)境關(guān)聯(lián)了一個變量對象击奶。環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。
全局執(zhí)行環(huán)境是最外圍的執(zhí)行環(huán)境责掏,全局執(zhí)行環(huán)境被認(rèn)為是window對象柜砾,因此所有的全局變量和函數(shù)都作為window對象的屬性和方法創(chuàng)建的。
js的執(zhí)行順序是根據(jù)函數(shù)的調(diào)用來決定的换衬,當(dāng)一個函數(shù)被調(diào)用時痰驱,該函數(shù)環(huán)境的變量對象就被壓入一個環(huán)境棧中证芭。而在函數(shù)執(zhí)行之后,棧將該函數(shù)的變量對象彈出担映,把控制權(quán)交給之前的執(zhí)行環(huán)境變量對象废士。
舉個例子:
當(dāng)某個函數(shù)第一次被調(diào)用時,就會創(chuàng)建一個執(zhí)行環(huán)境以及相應(yīng)的作用域鏈另萤,并把作用域鏈賦值給一個特殊的內(nèi)部屬性([scp])湃密。然后使用this,arguments和其他命名參數(shù)的值來初始化函數(shù)的活動對象四敞。當(dāng)前執(zhí)行環(huán)境的變量對象始終在作用域鏈的第0位
以上面的代碼為例,可以看到fn1活動對象里并沒有scp變量拔妥,于是沿著作用域鏈(scp chain)向后尋找忿危,結(jié)果在全局變量對象里找到了scp,所以就返回全局變量對象里的scp值没龙。
啰嗦這么多铺厨,接下來我們看看如何延長一個作用域鏈。
其實回答很簡單硬纤,用with語句和try catch 都可以延長作用域鏈解滓。
對 with 來說,將會指定對象添加到作用域鏈中筝家。將特定的變量對象保存在作用域鏈的最上層洼裤。
對 catch 來說,會創(chuàng)建一個新的變量對象溪王,其中包含的是被拋出的錯誤對象的聲明腮鞍。
(with)例:
with語句將sMessage對象提升到了作用域鏈的最前端,相當(dāng)于原來window的位置莹菱,而原來的AO對象就處于其下方移国,也就相當(dāng)于延長了作用域鏈。
(try catch)例:
try-catch語句在JavaScript中用來處理異常道伟,在catch(err){}中的錯誤對象組成了一個新的變量對象然后被加到了作用域的最前端迹缀。