📓
Something About JavaScript
  • Introduction
  • Day 1:前言
  • Day 2:資料型態的夢魘——動態型別加弱型別(1)
  • Day 3:資料型態的夢魘——動態型別加弱型別(2)
  • Day 4:動態型別加弱型別不是罪——怎麼 JavaScript 一摔就變成個印度阿三?
  • Day 5:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (1)
  • Day 6:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (2)
  • Day 7:傳統 var 關鍵字的不足
  • Day 8:var 掰掰 —— ES6 更嚴謹安全的 let 和 const
  • Day 9:圖解變數作用域(Scope)
  • Day 10:程式也懂電梯向上? —— Hoisting
  • Day 11:Strict Mode (嚴謹模式)
  • Day 12:看 Strict Mode 如何施展「還我漂亮拳」(1)
  • Day 13:看 Strict Mode 如何施展「還我漂亮拳」(2)
  • Day 14:來挖挖恐龍骨 —— with 語法
  • Day 15:this 關鍵字 (1)
  • Day 16:this 關鍵字 (2)
  • Day 17:this 關鍵字 (3)
  • Day 18:this 關鍵字 (4)
  • Day 19:函數定義 (Function Definition) 的 100 種寫法
  • Day 20:ES6 的箭頭函數 (Arrow Functions)
  • Day 21:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (1)
  • Day 22:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (2)
  • Day 23:ES6 物件實字威力加強版 (Enhanced Object Literals)
  • Day 24:函數呼叫 (Function Invocation) 與立即函數 (Self-Invoking Functions)
  • Day 25:不是多了塊魚 —— 立即函數的應用整理
  • Day 26:程式界的哈姆雷特 —— Pass by value, or Pass by reference?
  • Day 27:別管變數 Pass by Whatever,尋找容易理解的銀色子彈 (Silver Bullet)
  • Day 28:閉包 (Closures)
  • Day 29:閉包 (Closures) 進階打怪實戰
  • Day 30:ES10 醞釀中 —— 擁抱 JS の 未來
Powered by GitBook
On this page
  • 星爺強碰阿湯哥誰會贏?Global Scope vs. Function Scope
  • Block Level Scope
  • Block Scope 的 Java 例子
  • JavaScript 的 var 在 Block Scope 使用的例子
  • 對,傳統 JavaScript 只有 Global 和 Function 兩種等級的作用域
  • References

Was this helpful?

Day 6:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (2)

PreviousDay 5:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (1)NextDay 7:傳統 var 關鍵字的不足

Last updated 4 years ago

Was this helpful?

星爺強碰阿湯哥誰會贏?Global Scope vs. Function Scope

(Source: / )

俗話說天高皇帝遠,十里外的瀑布不如眼前的一杯水。

全球來說,在杜拜第一高樓跳來跳去的阿湯哥毫無疑問有較廣泛的知名度。但對我們而言,星爺在我們的生活中有更深的影響力。

Global 變數和 Local 變數也是如此。

也許對整個程式來說,Local 變數不及 Global 變數效用來得廣,但在函數的 Local 範圍內,Local 變數的存在感比較高。

所以如果 Global 和 Function 內宣告了同樣名稱的變數,在 Function 內會是 Local 變數生效,Function 外依然是 Global 稱王。

如下面這個例子:

function myFunc(){
    var n1 = "Stephen Chow";
    console.log("myFunc(): n1=", n1);
    console.log("myFunc(): this.n1=", this.n1);
    console.log("myFunc(): window.n1=", window.n1);
}

var n1 = "Tom Cruise";
myFunc();
console.log("Global: n1=", n1);

執行結果:

myFunc(): n1= Stephen Chow
myFunc(): this.n1= Tom Cruise
myFunc(): window.n1= Tom Cruise
Global: n1= Tom Cruise

要注意的是,如果在 Function 內透過如 window.n1 的方式,明確表明「我要取的是 Global 變數的 n1,而不是 Local 的 n1」,一樣會是 Global 變數發揮效用。

Block Level Scope

除了 Global Level 和 Function Level,還有第三種等級:Block Level。

Block Level 就像住在你家隔壁號稱歌神的里長阿伯。

不要小看他們,也許不要說離開這個縣市,可能出了這一里就沒人認得他們,但在這一里的範圍內,他們就是婆婆媽媽們心中最強的情歌王子。

Block Level 的作用域範圍可能非常小,只是一個函數裡的某一段程式。

程式裡 Block 指的是一段用大括號 ({ 和 }) 包起來的區塊。

我們用 Java 來舉例:

(為什麼用 Java 舉例而不是用 JavaScript,你馬上就會知道)

Block Scope 的 Java 例子

以下是一段 Block 的例子:

public static void main(String []args){
    {
        int x = 10;
        System.out.println(x);
    }
}

執行結果:

10

很正常印出 x 的值,好像沒什麼異狀。

我們改在 Block 外面去呼叫 x 變數:

public static void main(String []args){
    {
        int x = 10;
    }
    System.out.println(x);
}

執行結果:

HelloWorld.java:7: error: cannot find symbol
        System.out.println(x);
                           ^
  symbol:   variable x
  location: class HelloWorld
1 error

Java 編譯器說他不認得 x 這個變數。

這就是 Block Scope 的效果。雖然在同一個 Function 內,只要一出 Block,變數就失去效用。

JavaScript 的 var 在 Block Scope 使用的例子

輪到 JavaScript 上場了!

我們一樣在 Block 內宣告變數,預期出了 Block 就不認得 n1 變數:

{
   var n1 = "OneJar";
}
console.log("Global: n1=", n1);
console.log("Global: this.n1=", this.n1);
console.log("Global: window.n1=", window.n1);

執行結果:

Global: n1= OneJar
Global: this.n1= OneJar
Global: window.n1= OneJar

怎麼還是印得出來?而且是個全域變數。

一定有什麼誤會,可能只有 Function 內的 Block 有效,我們改在 Function 內的小 Block 去宣告:

function myFunc(){
    {
       var n1 = "OneJar";
    }
    console.log("myFunc(): n1=", n1);
    console.log("myFunc(): this.n1=", this.n1);
    console.log("myFunc(): window.n1=", window.n1);
}

myFunc();

執行結果:

myFunc(): n1= OneJar
myFunc(): this.n1= undefined
myFunc(): window.n1= undefined

還是印得出來,雖然不再是 Global 變數,但看起來是 Function Level Scope,而不是上面所描述的 Block Scope。

到底怎麼回事?

對,傳統 JavaScript 只有 Global 和 Function 兩種等級的作用域

剛剛一大段 Block Scope 都在講辛酸的嗎?

放心,都找了舞棍阿伯出來站台,怎麼可能是假的。

確實在 ES5 以前,用 var 關鍵字去宣告的變數,只會有 Global Level 和 Function Level 兩種等級的作用域。

ES6 導入了新的變數宣告關鍵字:let 和 const,不僅提高變數控管的嚴謹性,也增加了 Block Scope 的用途。

明天後面的文章我們就來介紹 ES6 的 let 和 const。

References

(Source: )

(Source: )

(Source: )

(Source: )

W3Schools - JavaScript Scope
網路1
網路2
網路
網路
網路
Youtube