用程式說明。
function hoist(i) {
console.log('input - ' + i);
for (var i=0; i<5; i++) {
console.log('loop - ' + i);
}
console.log('return - ' + i);
return i;
}
hoist(3);
傳入 i = 3,第一行輸出 input - 3,沒有問題。然後進入迴圈,重新命名 i,從 0 加到 4,因而輸出 loop - 1 ~ 4,這也可以理解。
問題在 return 應該是多少?
按照 Block-scoped 概念,應該是 return - 3,錯!
Javascript 是 Function-scoped,所以得到 return - 5。
input - 3 loop - 0 loop - 1 loop - 2 loop - 3 loop - 4 return - 5Javascript 對於變數定義的 scope,並不是找最接近的 statement 或者 block,而是最接近的 function。
因此,Javascript 會將上述的程式改寫成以下的方式。
function hoist(i) {
console.log('input - ' + i);
var i;
for (i=0; i<5; i++) {
console.log('loop - ' + i);
}
console.log('return - ' + i);
return i;
}
將原本是 Block-scoped 的變數 i 向上拉生成 Function-scoped。但有一個例外,就是在 catch 區裡的錯誤物件不會被拉升。
function hoistInError(e) {
console.log('input - ' + e);
try {
throw 'Oh! NO!';
}
catch (e) {
console.log('error - ' + e);
}
console.log('return - ' + e);
return e;
}
hoistInError("I'm ok!");
得到以下的結果。input - I'm ok! error - Oh! NO! return - I'm ok!因此,Effective Javascript #12 建議,自己手動拉升可以避免程式閱讀困惑的產生。
---
---
---
這個我在寫的時候沒注意過,基本上都是用不同的名字
回覆刪除作者已經移除這則留言。
回覆刪除