範圍鏈 Scope Chain

解析下方範例:

  1. 呼叫outer(a)帶入參數a 進去outer()內部
  2. 看到outer()內部呼叫inner(b*3)
  3. 進入inner(c)內部,印出a,b,c
  4. 此時已知 c = 6因為 a=1, b=a2=2, c=b3=6
  5. 但是b,c必須往外找在inner()的外面找到b
  6. 在outer()外面找到a
  7. 印出 1, 2, 6
1
2
3
4
5
6
7
8
9
10
11
12
function outer() {

var b = a * 2;

function inner(c) {
console.log(a, b, c);
}
inner(b * 3);
}

var a = 1;
outer(a);

從上面範例可以看出在inner()內部是找不到a,b變數的,因為往外去尋找,而這個往外尋找的動作就稱為範圍鏈

練習題

這邊result印出結果是什麼呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var msg = "global."

function outer() {
var msg = "local."

function inner() {
return msg;
}

return inner;
}

var innerFunc = outer();
var result = innerFunc();

console.log( result ); // ?
  1. 先看result等於innerFunc()
  2. 再看到innerFunc()等於outer()
  3. 看到outer()內,return inner()
  4. 看到inner()內,return msg
  5. 這邊因為inner內部找不到變數msg所以往外找找到了 = local.
  6. 故印出local.

這題的考點是:

  1. 外部環境的連結是在函式宣告當下就決定了而不是在乎叫的時候
  2. 所以inner的外層就是outer也就可以在這找到msg變數

當內部 (inner) 函式被回傳後,除了自己本身的程式碼外,也可以 穿越 取得了內部函式「當時環境」的變數值,記住了執行當時的環境,這就是「閉包」。