1、JavaScript的作用域鏈
首先看下下面這段代碼:
var rain = 1;
function rainman(){
? ? var man = 2;
? ? function inner(){
? ? ? ? var innerVar = 4;
? ? ? ? alert(rain);
? ? }
? ? inner();? ? //調(diào)用inner函數(shù)
}
rainman();? ? //調(diào)用rainman函數(shù)
觀察alert(rain);這句代碼。JavaScript首先在inner函數(shù)中查找是否定義了變量rain,如果定義了則使用inner函數(shù)中的rain變量;如果inner函數(shù)中沒(méi)有定義rain變量,JavaScript則會(huì)繼續(xù)在rainman函數(shù)中查找是否定義了rain變量,在這段代碼中rainman函數(shù)體內(nèi)沒(méi)有定義rain變量,則JavaScript引擎會(huì)繼續(xù)向上(全局對(duì)象)查找是否定義了rain;在全局對(duì)象中我們定義了rain = 1,因此最終結(jié)果會(huì)彈出'1'。
作用域鏈:JavaScript需要查詢一個(gè)變量x時(shí),首先會(huì)查找作用域鏈的第一個(gè)對(duì)象,如果以第一個(gè)對(duì)象沒(méi)有定義x變量,JavaScript會(huì)繼續(xù)查找有沒(méi)有定義x變量,如果第二個(gè)對(duì)象沒(méi)有定義則會(huì)繼續(xù)查找,以此類推。
上面的代碼涉及到了三個(gè)作用域鏈對(duì)象,依次是:inner、rainman、window。
2、函數(shù)體內(nèi)部,局部變量的優(yōu)先級(jí)比同名的全局變量高。
var rain = 1;? ? //定義全局變量 rain
function check(){
? ? var rain = 100;? ? //定義局部變量rain
? ? alert( rain );? ? ? //這里會(huì)彈出 100
}
check();
alert( rain );? ? //這里會(huì)彈出1
3、未使用var關(guān)鍵字定義的變量都是全局變量。全局變量都是window對(duì)象的屬性。
理解:內(nèi)部環(huán)境可以通過(guò)作用域鏈訪問(wèn)所有的外部環(huán)境,但是外部環(huán)境不能訪問(wèn)內(nèi)部環(huán)境中的任何變量和函數(shù)。 這些環(huán)境之間的聯(lián)系是線性的、有次序的。
但是有一類可以訪問(wèn)到內(nèi)部的變量,這種方式被稱作閉包。一個(gè)局部變量會(huì)在函數(shù)執(zhí)行開(kāi)始時(shí)候被初始化,函數(shù)結(jié)束時(shí)銷毀,但是如果在局部變量外部引用到了函數(shù)內(nèi)部的變量,此時(shí)這個(gè)函數(shù)就不會(huì)被銷毀了,這也是為什么閉包內(nèi)部的變量一直都存在在內(nèi)存的原因。