前言
在理解作用域鏈之前先要知道執行環境。任何函式都有一個執行環境,最外圍的是全域性執行環境,每一個環境都有自己的活動物件,活動物件裡面存在的是當前環境中的變數。
作用域鏈
當程式碼在一個環境中執行時,會建立變數物件的一個作用域鏈(scope chain)。作用域鏈裡存放的是當前環境以及外部環境的活動物件。作用域鏈的最前端的活動物件始終是當前環境的,下一級就是外部環境,再下一個活動物件來自再下一級的外部環境。當前環境活動物件裡如果沒有包含函式中使用的變數,那麼會沿著作用鏈去找下一個環境中的活動物件,直到全域性環境。這樣說可能太晦澀難懂了, 讓我們分析一段程式碼:
var a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
var fn = fn1()
fn() //2
複製程式碼
執行fn1其中var a = 2
已經成功定義並且a被賦值2,將fn3賦予了fn然後執行fn也就是執行fn3,在fn3中a被定義並賦值4,然後執行了fn2最終結果是2,說明了fn2是從fn1中的活動物件裡找到的a。
那我們來看一下圖:
var a = 1
function fn1(){
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
function fn2(){
console.log(a)
}
var fn = fn1()
fn() //1
複製程式碼
上面的程式碼最終輸出的是1.說明fn2是從全域性活動物件裡查詢到a的宣告,所以查詢順序那我們應該看宣告fn2的環境,而不是呼叫fn2的環境。 看圖: