JavaScript核心概念 - 範圍鍊

再次思考作用域與執行環境的關係

首先,若忘記語法作用域與執行環境可以先參考這兩篇(語法作用域執行環境與執行堆疊)。
我們在語法作用域時有提到 callName()的範例,因此我們可以得知 CallName2() 內在調用 CallName1() 時,CallName1()內的變數 name 會查找到全域變數的值 ASin ,所以我們了解到在撰寫原始碼時就已經定義好它的作用域,與他的執行環境變沒有關聯

1
2
3
4
5
6
7
8
9
var name = 'ASin';
function callName1() {
console.log(name);
}
function CallName2() {
var name = 'HYH';
callName1();
}
CallName2(); // ASin

範圍鍊

延伸上面的範例,其實兩個 function 已經各自產生了一個範圍鍊,當本身的 function 內找不到變數時,會再往外層尋找,這樣將查找範圍又延伸到外層一層一層出去,就是範圍鍊的形成。痾….,這範圍好像有點短,我們再來看下面的範例。
範圍鍊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var person = 'ASin';
function sayHello() {
console.log('Hello ' + person);
}
function meetSomeone() {
var person = '漂亮的HYH';
function meetHYH() {
function sayHelloToHYH() {
console.log('哈囉~ ' + person);
}
sayHelloToHYH();
}
sayHello();
meetHYH();
}
sayHello(); // Hello ASin
meetSomeone(); // Hello ASin & 哈囉~ 漂亮的HYH
  • 當我們執行sayHello()時,由於函式內並沒有person這個變數,所以往外層全域來查找找到了 ‘ASin’ 。
  • 那麼在執行meetSomeone()時,裡面調用了sayHello(),記得我們說過作用域早已經定義好了,雖然在meetSomeone()內調用,但它會忽視var person = '漂亮的HYH',所以在sayHello()原始碼往外一層就是全域,同樣找到了’ASin’。
  • 接下來執行meetHYH(),裡面調用了sayHelloToHYH(),所以sayHelloToHYH()從他原始碼已定義好的作用域開始查找變數person,嗯…函式本身沒有person,再往外一層 → meetHYH()內…..還是沒有找到,再往外一層 → meetSomeone()內….發現person!!!終於讓我找到妳啦!所以 console 印出了哈囉~ 漂亮的HYH的結果。

meetSomeone()我們可以知道,當查找不到變數時會往外一層一層的找(範圍鍊),而從哪裡開始查找則是看他已定義好的作用域,而不是執行環境。

0%