在《Javascript高級程序設計》這本書中學到的知識,覺得對於JS學習還是有很大幫助的,所以就寫上來跟大家分享一下。
首先我們來看一下執行環境。用例子來說明:
var backgroundColor='red';
function changeColor(){
if(backgroundColor=='red'){
backgroundColor='blue';
}
}
changeColor();
alert(backgroundColor);
上面的結果是blue。然而,我們分析一下它的執行過程。每一個函數都有執行環境,當這個函數執行的時候,這個執行環境就會進入環境棧中,函數結束後就會被棧彈出。在這個環境中會產生一個AO(Active 0bject)對象,最開始這個AO對象只有一個變量:argument,但隨着作用域鏈,backgroundColor這個對象也存在了AO對象的一個變量中,所以,changeColor的執行過程是這樣的:
①產生一個AO對象,一開始只有argument變量: ActiveObject{argument}
②沿着作用域鏈,ActiveObject{argument,backgroundColor:'blue'}
③接着就彈出對話框,其中的信息是ActiveObject.backgroundColor,也就是blue。
上面不斷提到作用域鏈的問題,到底什麼是作用域鏈呢?我們首先來看一下作用域,換一個例子:
var color='blue';
function a(){
var backColor='red';
function b(){
var fontColor='black';
//這裏能夠訪問color,backColor,fontColor
}
//這裏能夠訪問color backColor 但不能訪問fontColor
b();
}
//這裏只能夠訪問 color
a();
從上面的例子註釋,我們可以很容易理解作用域的概念,就是變量在哪個地方能夠被訪問。要注意,js是沒有塊級作用域的。然後,我們來說說開始的例子作用域鏈的問題,產生AO對象的時候,它會在函數changeColor中找變量,發現裏面並沒有聲明任何變量(即沒有var一個變量),所以,沿着作用域鏈,查找比changeColor範圍還要廣的作用域,即是全局作用域,就發現了backgroundColor。這就是作用域鏈:保證對執行環境有權訪問的所有變量和函數的有序訪問。
最後,我們來看一看一個經典的面試題
var str='global';
function a(){
alert(str);
var str='local';
alert(str);
}
a();
大家想到結果沒有? 第一個是undefined ,第二個是local。 有沒有大驚小怪?
不過相信大家看了上面的知識,理解這道題就沒什麼難度了。
大家不要被全局變量str="global"誤導了,其實這個並沒什麼作用
有作用的是a函數裏面的var str='local',在變量定義的時候,其實編譯器會先把變量聲明瞭 再給它賦值的,也就是其實上面的代碼是這樣的:
function a(){
var str;
alert(str);
str='local';
alert(str);
}
接着,就產生一個AO對象,裏面首先是alert(AO.str)一開始的時候,str=undefined的所以會輸出undefined,接着str賦值爲local,就會輸出AO.str='local'.
好了,這部分大概就這麼多了,大家可以把這個面試裏a函數裏面的var去掉,看看結果什麼,如果和你預想一樣,這部分我相信你也能夠理解了。