iT邦幫忙

2025 iThome 鐵人賽

DAY 11
0
Modern Web

30天入門Java Script系列 第 11

Day11:作用域與閉包

  • 分享至 

  • xImage
  •  

到目前為止,我們一直在宣告變數、寫函式,但有沒有發現:同樣一個變數名稱,在不同地方可能會「互不影響」?
這就是作用域:變數在哪裡可用、存活多久。

1. 什麼是作用域

簡單說,作用域就是變數可以被存取的範圍。
在 JS 裡主要有兩種常見範圍:

全域:整支程式都能讀到。
區塊/函式作用域:只在某個 {} 裡面或函式裡面有效。

let x = 10; // 全域範圍

function test() {
  let y = 5; // 區塊/函式範圍
  console.log(x); // 可以讀到全域的 x
  console.log(y); // 5
}

test();
console.log(x); // 10
console.log(y); // ❌ 會報錯,y 不在全域範圍

var只有函式作用域,沒有區塊作用域,所以在iffor內宣告的var會跑出來
跑出去let/const則有,比較安全

2. 作用域鏈

如果程式在某個範圍找不到變數,就會往外層找,一層一層往外找,這叫做作用域鏈

let a = 1;

function outer() {
  let b = 2;
  function inner() {
    let c = 3;
    console.log(a, b, c); // 1 2 3
  }
  inner();
}

outer();

inner找不到a會往外找,找不到b也會往外找,所以它可以讀到外層的東西。

3. 什麼是閉包

閉包聽起來很神秘,其實就是「一個函式記住它出生時的外部環境,即使外部函式已經執行完畢。」
範例:

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

const counter1 = makeCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2
console.log(counter1()); // 3

makeCounter執行後本來應該結束,count變數理論上要消失,但因為回傳的函式「閉包」記住了外層的 count,所以count還能繼續用,而且每個makeCounter都有自己的count

為什麼閉包很重要?可以做「私有變數」,不暴露在全域;或是可以保存狀態,像計數器、暫存資料,很多 JS API(事件監聽、setTimeout 等)都是靠閉包工作的

小練習

寫一個函式,它回傳另一個函式,每次呼叫都會印出 Hello, name!

function createGreeter(name){
  return function(){
    console.log(`Hello, ${name}!`);
  }
}

const greetAlice = createGreeter('Alice');
greetAlice(); // Hello, Alice!
greetAlice(); // Hello, Alice!

這就是閉包:greetAlice 記住了 name。

總結一下:作用域決定了變數在哪裡能被存取,let/const有區塊作用域,var只有函式作用域。
閉包就是函式記住外部變數的能力,閉包常用來做私有變數、保存狀態


上一篇
Day10:ES6 解構賦值與展開運算子
下一篇
Day12:函式表達式與箭頭函式
系列文
30天入門Java Script14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言