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

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

![](https://i.imgur.com/KkQVLtA.png)\
(Source: [網路1](https://puui.qpic.cn/qqvideo_ori/0/k0505psezun_496_280/0) / [網路2](https://globedia.com/imagenes/noticias/2015/9/4/mision-imposible-tom-cruise-corre-horas_1_2287136.jpg))

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

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

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

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

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

如下面這個例子：

```javascript
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。

![](https://i.imgur.com/PPHpxvt.jpg)\
(Source: [網路](https://i.ytimg.com/vi/GbBdx9uwe4o/maxresdefault.jpg))

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

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

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

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

我們用 Java 來舉例：

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

### Block Scope 的 Java 例子

以下是一段 Block 的例子：

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

執行結果：

```
10
```

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

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

```java
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` 變數：

```javascript
{
   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
```

![](https://i.imgur.com/Xx9HKan.png)\
(Source: [網路](https://vignette.wikia.nocookie.net/evchk/images/e/ec/2471912.jpg/revision/latest?cb=20171012125530))

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

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

```javascript
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
```

![](https://i.imgur.com/FKU24ly.png)\
(Source: [網路](https://vignette.wikia.nocookie.net/evchk/images/e/ec/2471912.jpg/revision/latest?cb=20171012125530))

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

到底怎麼回事？

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

![](https://i.imgur.com/GLkuwLF.png)\
(Source: [Youtube](https://www.youtube.com/watch?v=o9US59aO71s))

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

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

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

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

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

## References

* [W3Schools - JavaScript Scope](https://www.w3schools.com/js/js_scope.asp)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://something-about-js-book.onejar99.com/day06.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
