作用域鏈
作用域的原理: ”JavaScript中的函數(shù)運(yùn)行在它們被定義的作用域里,而不是它們被執(zhí)行的作用域里.”
所以函數(shù)的作用域其實(shí)是在它們被定義的那時(shí)就決定降传,和運(yùn)行時(shí)沒啥關(guān)系咧叭∏莩担看下面這個(gè)簡單的例子:
var name = 'world';
function echo() {
alert(name); //undefined
var name = 'hello';
alert(name); //hello
alert(age); //error
}
echo();
這個(gè)例子其實(shí)等于下面這個(gè)缴挖,就是把局部變量定義提升了:
var name = 'world';
function echo() {
var name;
alert(name); //undefined
name = 'hello';
alert(name); //hello
alert(age); //error
}
echo();
這樣就好理解了务热。
預(yù)編譯
直接看例子吧:
<script>
alert(typeof eve); //結(jié)果:function
alert(typeof walle); //結(jié)果:undefined
function eve() { //函數(shù)定義式
alert('hello world');
};
var walle = function() { //函數(shù)表達(dá)式
}
alert(typeof walle); //結(jié)果:function
</script>
在JavaScript里,在調(diào)用函數(shù)執(zhí)行之前, 會首先創(chuàng)建一個(gè)活動對象, 然后搜尋這個(gè)函數(shù)中的局部變量定義(var),和函數(shù)定義(function), 將變量名和函數(shù)名都做為這個(gè)活動對象的同名屬性, 對于局部變量定義,變量的值會在真正執(zhí)行的時(shí)候才計(jì)算, 此時(shí)只是簡單的賦為undefined.
改變(延長)作用域
- with語句吓笙,會將指定對象添加到作用域鏈中淑玫,這個(gè)對象將被推入作用域鏈的頭部,這意味著函數(shù)的所有局部變量現(xiàn)在處于第二個(gè)作用域鏈對象中面睛,因此訪問代價(jià)更高了絮蒿。實(shí)際使用時(shí)要避免使用with語句。
- try-catch語句的catch塊叁鉴,當(dāng)try代碼塊中發(fā)生錯(cuò)誤時(shí)土涝,執(zhí)行過程會跳轉(zhuǎn)到catch語句,然后把異常對象推入一個(gè)可變對象并置于作用域的頭部幌墓。在catch代碼塊內(nèi)部但壮,函數(shù)的所有局部變量將會被放在第二個(gè)作用域鏈對象中。以下例子可以優(yōu)化代碼性能:
try {
doSomething();
} catch (ex) {
handleError(ex); //委托給處理器方法
}