iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0
自我挑戰組

一個月的後端學習之旅系列 第 20

【DAY20】作用域、閉包

  • 分享至 

  • xImage
  •  

作用域 Scope

是指在當前的 execution context 之中,變數的可訪問性accessibility 為何?(variable scope 為何?)

我們在 function A 所宣告的變數,在 function B 內部可以使用(訪問)嗎? => 不可以

function hello() {
  let a = 10;  // 變數a的可訪問性,只有hello()這個function才可以訪問a
  console.log(a);
}

hello();

function hello2() {
    console.log(a);  // a是定義在hello()裡面,那hello2()可不可以去訪問變數a? => 不可以
}

hello2(); // -> ReferencrError a is not defined

另一個例子,hello2()可以訪問到的全域變數 global variable 的 x = 10 嗎? -> 可以

let x = 10;  //定義在最外層的變數叫全域變數global variable
function hello() {
    function hello2() { // 抓的到外層的變數值
    console.log(x + 10);
  }
  hello2();
}

hello(); // -> 20

了解 Scope 可以知道,每個變數在哪些區域或範圍是有意義的,或者是說,變數在哪些區域是可訪問可使用

JavaScript 的變數有以下幾種 Scope:

  • Global scope: The default scope for all code running in the script
    varletconst都有 Global scope

  • Module scope: The scope for code running in module mode

  • Function scope: The scope is created with a function
    varletconst、function declaration都有Function scope

    function sayHi() {
      console.log("hello");
    
      // function declaration也有Function scope
      function sayHi2() {
        console.log("hello2");
      }
    }
    

sayHi2(); // -> ReferenceError sayHi2 is not defined

此外,用 let 或是 const 去宣告的變數屬於下面這個額外的 scope:(沒有var)

  • Block scope: The scope created with a pair of curly braces -> {} (a block)
    會出現在兩種地方

    if statement

    if (true) {
      let x = 10; // -> Block scope,可訪問區域只限在大括弧中
    }
    console.log(x); // -> ReferencrError x is not defined
    

    loop

    for (let i = 0; i < 20; i++){}
    console.log(i); // -> ReferencrError i is not defined
    

    用var是全可訪問,不會被大括弧侷限

    // if statement
    if (true) {
      var x = 10;
    }
    console.log(x); // -> 10
    
    // loop
    var x = 100;
    
    // redeclaration, reassignment
    for (var x = 0; x < 10; x++){}
    
    console.log(x); // -> 10
    

閉包 Closure

在函式執行環境function execution context中,如果發現不在function scope內部的變數,JavaScript 將轉到其他地方查找

閉包Closure就是指這種將函數與其周圍的狀態或語詞環境結合在一起的組合

function add(a, b){
    // argument object a = 3, b = 4, c = 如果function內部找不到,就會向外找,組合起來就是Closure
    return a + b + c;
}

add(3, 4); // -> 7

在 JavaScript 中,每次function execution context都會在creation phase創建closure

Closure的規則是:

  1. 從Argument Object以及local variable去尋找
let c = 100;

function add(a, b) {
  let c = 5;
  return a + b + c; // -> 3 + 4 + 5,先找argument object,再找local variable
}

add(3, 4); // -> 12
  1. 若從1找不到,則從記憶體RAM被分配給函數的位置開始尋找
let myName = "Phoebe";

function sayHi() {
  let myName = "Darren";

  console.log(myName + "說你好"); // -> Darren說你好
  sayHi2(); // -> Phoebe說你好
}

function sayHi2() {
  console.log(myName + "說你好");
}

sayHi();
// -> Darren說你好 
// -> Phoebe說你好

let myName = "Phoebe";

function sayHi() {
  let myName = "Darren";

  console.log(myName + "說你好"); // -> Darren說你好
  sayHi2(); // -> Darren說你好

  function sayHi2() {
    console.log(myName + "說你好");
  }
}

sayHi();
// -> Darren說你好 
// -> Darren說你好
  1. 若在目前的execution context找不到,就繼續往外層、往全域一層一層的去找

下一篇文章學習進階的遞迴、費波那契數列。


上一篇
【DAY19】提升 Hoisting
下一篇
【DAY21】遞迴、費波那契數列
系列文
一個月的後端學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言