iT邦幫忙

2021 iThome 鐵人賽

DAY 2
0
自我挑戰組

登堂入室!前端工程師的觀念技術 _30_ 題系列 第 2

1. 解釋 Scope ( Global scope / Function scope / Block scope )

2021.9.3更新: 調整了一些block scope的敘述。

Scope 的定義


scope 可以翻譯成作用域,意即 variable能被調用的範圍

→ 也就是說,如果一個variable不在當下執行的scope裡,對當前的scope來說根本看不到variable這個東西,所以沒辦法調用。

(補充: 在JS裡,所有的object和function也都是variable。)

而 scope 又分為

  1. Global scope
  2. function scope
  3. Block scope (ES6後新增)

1. Global Scope


只要一個variable宣告在所有的function之外,我們將variable稱為 global variable(全域變數)。

被宣告為global variable就會擁有Global Scope。

這會造成整個script都是它的作用域! 而該頁面的所有的funciton和script都可以調用它。

舉例來說:

// a has Global Scope; All scripts can access it. 

let a = "apples"

console.log( "Winnie would eat " + a); 
// output: Winnie would eat apples.
// a has Global Scope; All functions can access it. 

let a = "apples"

function eat(){
    console.log( "Mary would eat " + a); 
}

eat();  // output: Mary would eat apples.

以上面的舉例而言,因為a被宣告在eat()這個function外,所以不管在function裡或整個script都可以有效的印出a。

2. Function Scope


在JS裡,每一個function都會有一個Function Scope。

被定義在function內部的variable,便不能在function外被調用。

再看個例子:

// a isn't accessible (visible) from outside the function.

function f(){
    let a = "apple";
}

console.log( "Mary would eat " + a); 
// ReferenceError: a is not defined

a被宣告在f()裡,因此想從f()外調用a就會出現ReferenceError,意思是對整個global來說a並不存在。

// a is accessible in the function

function f(){
    let a = "apple";
    console.log( "Mary would eat " + a); 
}

f();
// output: Mary would eat apple

a的scope就是function scope,而整個f()都是a可以被調用的範圍(scope)。

那如果是更多分層的函式呢? 可以在延伸到下一個例子:

// a is accessible in the f2()

function f(){
    let a = "apple";
    
    function f2(){
        console.log( "Winnie wouldn't eat " + a); 
    }
    f2();
}
f();
// output: Winnie wouldn't eat apple

MDN的文件有提到: 如果有階層關係,基本上子階層會可以調用父級階層裡的變數。

講白話是,像f2()是在f()裡的函式,但因為整個f()都是a的scope,所以在f2()裡調用a也會成功。

function f(){
    let a = "apple";
    
    function f2(){
        console.log( "Winnie wouldn't eat " + a); 
    }
}
f2(); // ReferenceError: f2 is not defined

最後是,因為function也是variable的一種,
這個例子的情況跟在f()外印出a是一樣的,都會造成讀不到f2

3. Block Scope


因為ES6新增了 letconst
這兩個 keyword 能建立 Block Scope

letconst的宣告,只在{大括號}中有效,無法從{}外被調用。
(→ let, var, const都有global scope和function scope,但只有letconst有block scope)

{block scope}通常指兩種情況:

  1. 在if statement裡面
  2. 在for Loop裡面
if(true){
    let a = "apple";
}
console.log(a);  // ReferenceError: a is not defined

var並沒有Block Scope,所以就算被寫在{大括號}裡,也可以從{}外被調用。

if(true){
    var a = "apple";
}
console.log(a);  // output: apple 

另一種block scope的情況,還有在for loop裡面:

for(let i=0; i<=10; i++){
    console.log(i); 
    // output: 0, 1, 2, ... 10
}

console.log("out of the loop: " + i); 
// ReferenceError: i is not defined

在(小括號)裡宣告let i=0,只能在{大括號}裡被調用。
出了{大括號}就會出錯。

for(var i=0; i<=10; i++){
    console.log(i);
    // output: 0, 1, 2, ... 10
}

console.log("out of the loop: " + i);
// out of the function: 11

在(小括號)裡宣告var i=0,在{大括號}外也可以成功被調用。

要注意這裡的{大括號}跟 function(){}的大括號是不一樣的,var定義在f(),如果從整個global調用,一樣是function scope的概念,所以會出錯。

function f(){
    var a = "apple";
    }
console.log(a);
// ReferenceError: a is not defined

---總結重點---

  • scope 可以翻譯成作用域,意即 變數能被調用的範圍

  • scope 又分為:

    1. Global scope : 變數在整個web page都可以被調用。
    2. Function scope : variable只能在Function內被調用。
      (在JS中,一個function會依照closure建立一個scope。)
    3. Block scope : let和const如果被宣告在{大括號}裡,{}外就不能調用let和const。

參考資料

JavaScript Scope - w3schools
Scope - MDN

【如內文有誤還請不吝指教>< 並感謝閱覽至此的各位:D 】

---正文結束---


上一篇
目錄 [10.12更新]
下一篇
2. 解釋 Closure ( Scope chain )
系列文
登堂入室!前端工程師的觀念技術 _30_ 題31

尚未有邦友留言

立即登入留言