用程式說明。
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 建議,自己手動拉升可以避免程式閱讀困惑的產生。
---
---
---
這個我在寫的時候沒注意過,基本上都是用不同的名字
回覆刪除作者已經移除這則留言。
回覆刪除