2023-10-02|閱讀時間 ‧ 約 3 分鐘

JS 學習筆記 #2 - 閉包 Closure

在談到閉包前,要先談談範圍鏈

範圍鏈 Scope Chain

在 ES6 以前,變數透過 var 宣告,當時切分變數的最小單位為「函式」,有以下特性需要留意:

  • 內層可以取得外層的變數,但外層無法取得內層變數
  • 在「定義」函式時就決定了範圍鏈,而非執行時

💥 範圍鏈地雷

  • 確認範圍是否有使用 function 切分
  • 若沒有宣告變數,即使在函式內,都會變成全域變數(最外層)

範例

let a = "A";

function fn1() {
let b = "B";
fn2();

function fn2() {
let c = "C";
//可以取得外層所有變數
console.log(a, b, c);
}
}

fn1();
//error,因為無法取得 b,c 變數
console.log(a, b, c);


認識完範圍鏈,就來看看閉包吧!

閉包 Closure

用途

  • 可避免產生全域變數,同時避免開發者變數命名衝突,是透過「內層可以向外取得外層變數、外層無法取得內層變數」的特性達成,也就是範圍鏈的概念
  • 當內部函式回傳時,等同取得內部函式當下環境的變數值(可以取得外層函式的變數值

作法

假設 a 是外部函式,b 是存在於 a 裡面的內部函式

  1. b 不會有自己的變數,但因為作用域的原理,可以取得 a 的變數
  2. 設定 a 函式會呼叫 b,就可以在 b 裡面針對 a 建立的變數進行操作,避免全域變數產生
  3. 之後開發者只需呼叫 a ,a 就會去呼叫 b

範例

以往做計數器時,會在全域環境宣告一個變數來記錄數字,會出現全域變數,造成多個開發者之間命名衝突

//全域變數
let count = 0;

function add() {
return ++count;
}

console.log(add());

使用閉包寫法

function addFunc() {
let count = 0;
function add() {
return ++count;
}
return add;
}

//addFunc() 會回傳 add() 整個 function
//之後呼叫 result 等同於呼叫 add() 這個內部函式
let result = addFunc();
console.log(result());

注意:若缺少 let result = addFunc() 這個動作,直接寫 addFunc(),回傳的會是 add 整個 function,而不是計算結果

希望看完這篇有更認識閉包這個觀念,若有錯誤也歡迎指正,謝謝看到這裡的大家。

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.