介紹一下JavaScript作用域鏈?
- 什么是作用域鏈
- 每個(gè)函數(shù)都有自己的 執(zhí)行環(huán)境 ,當(dāng)執(zhí)行流執(zhí)行到一個(gè)函數(shù)時(shí),函數(shù)的環(huán)境就會(huì)被推入到一個(gè) 環(huán)境棧 中,而在函數(shù)執(zhí)行之后,棧將其環(huán)境彈出,將控制權(quán)返給之前的執(zhí)行環(huán)境;
- 當(dāng)代碼在一個(gè)環(huán)境中訪問(wèn)時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè) 作用域鏈 。作用域鏈的用途,就是 保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)的有序訪問(wèn) ;作用域鏈的前端,始終都是 當(dāng)前執(zhí)行代碼所在環(huán)境的變量對(duì)象 。如果這個(gè)變量是函數(shù),則將其活動(dòng)對(duì)象作為變量對(duì)象;活動(dòng)對(duì)象在最開(kāi)始時(shí)只包含一個(gè)變量,即argumnets對(duì)象(這個(gè)對(duì)象在全局環(huán)境中是不存在的)。作用域鏈中的下一個(gè)變量對(duì)象來(lái)自包含環(huán)境,在下一個(gè)變量對(duì)象則來(lái)自再下一個(gè)包含環(huán)境。這樣,一直延續(xù)到 全局執(zhí)行環(huán)境。全局執(zhí)行環(huán)境始終是作用域鏈中的最后一個(gè)對(duì)象。
const color = 'red'
const function = sayColor(){
const innerColor = 'blue'
console.log(color)
}
sayColor() // 'red'
- 在上面的例子中,sayColor()的作用域鏈中包含兩個(gè)變量對(duì)象,他自己的活動(dòng)對(duì)象(其中包含著argumnets對(duì)象)和全局環(huán)境的變量對(duì)象
- 可以在函數(shù)內(nèi)部訪問(wèn)到變量color,就是因?yàn)榭梢栽谶@個(gè)作用域鏈中找到他;
- 內(nèi)部環(huán)境可以通過(guò)作用域鏈訪問(wèn)所有的外部環(huán)境,但是外部環(huán)境不能訪問(wèn)內(nèi)部環(huán)境的任何變量和函數(shù);這些環(huán)境之間的聯(lián)系是線性的,有次序的,每個(gè)環(huán)境都可以向上搜索作用域鏈,以查詢(xún)變量和函數(shù)名; 但是任何環(huán)境都不能向下搜索作用域鏈而進(jìn)入另一個(gè)執(zhí)行環(huán)境;
- 延長(zhǎng)作用域鏈
- 雖然執(zhí)行環(huán)境的類(lèi)型只有兩種,全局和局部(函數(shù)),但還是有其他方法來(lái)延長(zhǎng)作用域鏈,這么說(shuō)是因?yàn)椋梢酝ㄟ^(guò)一些手段,在作用域鏈的前端,臨時(shí)增加一個(gè)變量對(duì)象,這個(gè)變量對(duì)象會(huì)在代碼執(zhí)行之后被移除。這兩種情況下會(huì)發(fā)生這種現(xiàn)象,具體來(lái)說(shuō),當(dāng)執(zhí)行流進(jìn)行到下面任何一個(gè)語(yǔ)句時(shí),作用域鏈就會(huì)得到加長(zhǎng);
- try-catch語(yǔ)句的catch塊
- with語(yǔ)句
- 這兩個(gè)方法都會(huì)在作用域鏈的前端增加一個(gè)變量對(duì)象。對(duì)with語(yǔ)句來(lái)說(shuō),會(huì)將指定的對(duì)象添加到作用域鏈中。對(duì)ctach語(yǔ)句來(lái)說(shuō),會(huì)創(chuàng)建一個(gè)新的變量對(duì)象,其中包含的是被拋出的錯(cuò)誤對(duì)象的變量聲明;
function basicUrl(){
var qs = 'haha';
with(location){
return url = href + qs
}
return url;
}
basicUrl()
// "http://localhost:4000/Blog/haha"
- 在此,with 語(yǔ)句接收的是location對(duì)象,因此其變量對(duì)象中包含了location的所有屬性和方法,而這個(gè)變量對(duì)象被添加到了作用域鏈的前端。basicUrl()函數(shù)中定義了一個(gè)變量qs,當(dāng)在with語(yǔ)句中引用變量href時(shí)(實(shí)際引用的是location.href),可以在當(dāng)前執(zhí)行環(huán)境的變量對(duì)象中找到;當(dāng)引用變量qs時(shí),引用的則是basicUrl中定義的
qs,而該變量位于函數(shù)環(huán)境的變量對(duì)象中。至于with語(yǔ)句內(nèi)部,則定義了一個(gè)名為url的變量,因此url就成為了函數(shù)執(zhí)行環(huán)境的一部分,所以可以作為函數(shù)的值被返回。
function compare(value1, value2) {
if (value1 > value2) {
return 1;
} else if (value1 < value2) {
return -1;
} else {
return 0;
}
}
const result = compare(2, 3);
- 全局環(huán)境的變量對(duì)象始終存在,而象compare()函數(shù)這樣的局部環(huán)境的變量對(duì)象,僅在函數(shù)執(zhí)行的過(guò)程中存在。在創(chuàng)建compare()函數(shù)時(shí),會(huì)創(chuàng)建一個(gè)預(yù)先包含全局變量對(duì)象的作用域鏈,這個(gè)作用域鏈被保存在內(nèi)部的 [[Scope]] 屬性中。當(dāng)調(diào)用compare()函數(shù)時(shí),回味函數(shù)創(chuàng)建一個(gè)執(zhí)行環(huán)境,然后通過(guò)復(fù)制 [[Scope]] 屬性中的對(duì)象,構(gòu)建起執(zhí)行環(huán)境的作用域鏈。此后,又有一個(gè)活動(dòng)對(duì)象(在此作為變量對(duì)象使用)被推入執(zhí)行環(huán)境作用域鏈的前端。
- 對(duì)于這個(gè)例子中的compare()函數(shù)的執(zhí)行環(huán)境而言,其作用域鏈包含兩個(gè)變量對(duì)象,本地活動(dòng)對(duì)象和全局變量對(duì)象。
- 作用域鏈本質(zhì)上是一個(gè)指向變量對(duì)象的指針列表,他只引用但不實(shí)際包含變量對(duì)象
- 無(wú)論什么時(shí)候在函數(shù)中搜索一個(gè)變量時(shí),就會(huì)從作用域鏈中搜索具有相應(yīng)名字的變量,一般來(lái)講,當(dāng)函數(shù)執(zhí)行完畢后,局部活動(dòng)對(duì)象就會(huì)被銷(xiāo)毀,內(nèi)存中僅保存全局作用域(全局環(huán)境的活動(dòng)對(duì)象),但是閉包的情況有所不同
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。