2016年1月30日 星期六

[javascript] Hoisting & Scope

今天差點被奇怪的中文翻譯書給騙了 以為弄了那麼久竟然弄錯

只好寫下來紀錄一下

不過哥真的很認真

還有附圖 跟 live demo

----

Hoisting - 提升 - 意思是說 js 的變數宣告,其實會被默默地移至同一 scope 的開頭

因為是默默的,所以很容易有以下的誤解

http://embed.plnkr.co/jP72zKg7V3viYLAtGEeE/

var i = 0;

(function(){
    i = 5; // 很像是在操作上面那個全域的 i

    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行

    for(var i = 0 ; i < 10; i++){

    }
})()

alert(i); // ??? 是 0 還是 5 呢?


但是實際上會像是:

var i = 0;

(function(){
    var i;
    i = 5; // 很像是在操作上面那個全域的 i

    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行
    // 中間可能隔很多行

    for(i = 0 ; i < 10; i++){

    }
})()

alert(i); // 很明確是 0 沒錯了

所以如果可以,在 function 剛進來的地方宣告吧。
!!! 絕對不是在說多設定全域變數 !!!

----

Scope : 就是這個變數可以被人家使用的範圍

一般寫 c#, java 等語言,變數都是 block scope

意思是說從 宣告之後 到 目前所在的大括弧區間尾巴 (英文是一個 block ),都是可以使用的,一旦這個範圍還使用就噴錯了

但是 js 是 function scope 而且配合剛剛的 Hoisting 來說

可以使用的範圍是本變數所在的這個 function 從頭至尾都視做已經宣告

差別只是值被 assign 了沒有,undefined => assigned

然後有個比較特別的是直接宣告的 function

他是不管在哪兒宣告,都是在整個 scope 可見,就是被提升啦!!!!!!! (機車)

http://embed.plnkr.co/XgMeOjyD6AtMPtYdwayY/


範例一,只要宣告了那在前面使用這個變數是不會噴掉的!!!


範例二,就算是我們習慣的 block 也是一樣,超出了 block 值也還在喔


 範例三,那些在 function 之外的 access,噴!!! 直接就給你噴錯了!! 請小心

沒有留言:

張貼留言