語法作用域(Lexical scope)

JavaScript cover

1.語法作用域分為兩種:

1-1.靜態作用域:

變數的作用域在語法解析時,就已經確定了,不會再改變。

這也是JacaScript所採用的方式。

假設有一個函式如下方,執行後會得到預期的結果。

function people() {
  var name = '小明';
  console.log(name); //小明
}
people(); //小明

但如果稍微更改一下,結果就不一樣了,這是為什麼?

function people() {
  var name = '小明';
}
people();
console.log(name); //name is not defined

會造成這樣的原因是JavaScript是靜態作用域,要執行函式的內容必須要在大括號裡才能執行,離開大括號範圍就不會辨識,自然也就錯誤了。

Snipaste_2022-05-02_18-06-23.jpg

1-2.動態作用域:

變數的作用域在函式被調用時才決定。

2.函式運行模式

函式基本上作用域是各自為政,但如果內部有一個特定的變數需要調用時,會先查找自身有沒有這個變數,如果沒有就會往外部查找到全域,這樣還是沒有就會回報ReferenceError: variable is not defined的警告訊息,所以函式的查找規則是向外查找。

用以下例子來加深你對靜態作用域與動態作用域的理解吧。

var value = 1;

function f1() {
  console.log(value);
}

function f2() {
  var value = 2;
  f1();
}

f2(); //這個會是什麼?

2-1.靜態作用域的函式運作方式:

var value = 1;

function f1() {
  console.log(value);
}

function f2() {
  var value = 2;
  f1();
}

f2(); //1

在靜態作用域下的答案是1。

原因如下:

1.在全域下(最上方)定義一個變數為1。

2.執行函式f2,裡面先重新定義value=2,然後再執行f1。

3.但JS的語法作用域的因素下,value=2只會在f2內查找,然後f1的值在f2裡找不到,故往外去尋找。

4.最後找到全域變數,也就是最上面的var value = 1,所以答案就是1。

2-2.動態作用域的函式運作方式:

var value = 1;

function f1() {
  console.log(value);
}

function f2() {
  var value = 2; //動態作用域會找上一層的變數
  f1(); //出發去找
}

f2(); //2

因動態作用域是在函式調用時才會執行,所以答案是2。


參考資料

六角學院