這篇文章主要介紹了ES5中執(zhí)行環(huán)境和作用域的詳細(xì)介紹(代碼示例),具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),侯馬企業(yè)網(wǎng)站建設(shè),侯馬品牌網(wǎng)站建設(shè),網(wǎng)站定制,侯馬網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,侯馬網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。
執(zhí)行環(huán)境(execution context,為了簡單起見,有時也成為環(huán)境)是JavaScript中最為重要的一個概念。
執(zhí)行環(huán)境,定義了變量或函數(shù)有權(quán)訪問其他數(shù)據(jù),且決定了它們各自的行為。
每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象(variable object),環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。
雖然我們編寫的代碼無法訪問這個對象,但解析器在處理數(shù)據(jù)時會在后臺使用它。
全局執(zhí)行環(huán)境時最外圍的一個執(zhí)行環(huán)境。
根據(jù)ECMAScript實現(xiàn)所在的宿主環(huán)境不同,表示執(zhí)行環(huán)境的對象也不一樣。
在Web瀏覽器中,全局執(zhí)行環(huán)境被認(rèn)為是window對象,因此所有全局變量和函數(shù)都是作為window對象的屬性和方法創(chuàng)建的。
(變量的生命周期),某個執(zhí)行環(huán)境中的所有代碼執(zhí)行完畢后,該環(huán)境被銷毀,保存在其中的所有變量和函數(shù)定義也隨之銷毀)
全局執(zhí)行環(huán)境直到應(yīng)用程序退出——例如關(guān)閉網(wǎng)頁或瀏覽器時才會被銷毀。
每個函數(shù)都有自己的執(zhí)行環(huán)境。當(dāng)執(zhí)行流進(jìn)入一個函數(shù)時,函數(shù)的環(huán)境就會被推入一個環(huán)境棧中。在函數(shù)執(zhí)行之后,棧將其環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。ECMAScript程序中的執(zhí)行流正是由這個方便的機制控制著。
當(dāng)代碼在一個環(huán)境中執(zhí)行時,會創(chuàng)建變量對象的一個作用域鏈(scope chain)。
作用域鏈的用途,是保證對執(zhí)行環(huán)境,有權(quán)訪問的所有變量和函數(shù)的有序訪問。
作用域鏈的前端,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對象。(也可以理解為“就近原則”)。
如果這個環(huán)境是函數(shù),則將其活動對象(activation object)作為變量對象。
函數(shù)執(zhí)行環(huán)境中的活動對象在最開始時,只包含一個變量,即arguments對象(這個對象在全局環(huán)境中是不存在的)作為變量對象。
作用域鏈中的下一個變量對象來自包含(外部)環(huán)境,而再下一個變量對象則來自下一個包含環(huán)境,這樣,一直延續(xù)到全局執(zhí)行環(huán)境。
全局執(zhí)行環(huán)境的變量對象,始終是作用域鏈中的最后一個對象。
標(biāo)識符解析是沿著作用域鏈一級一級地搜索標(biāo)識標(biāo)識符的過程。
搜索過程始終從作用域鏈的前端開始,然后逐級向后回溯,直至找到標(biāo)識符為止(如果找不到標(biāo)識符,通過會導(dǎo)致錯誤發(fā)生)。
var color = "blue"; function changeColor() { if(color === "blue") { color = "red"; } else { color = "blue"; } } changeColor(); console.log("Color is now " + color); // "color is now red"
在這個簡單的例子中,函數(shù)changeColor()的作用域鏈包含兩個對象:
它自己的變量對象(其中定義著arguments對象)和全局環(huán)境的變量對象。
可以在函數(shù)內(nèi)部訪問變量color,就是因為可以在這個作用域鏈中找到它。
此外,在局部作用中定義的變量可以在局部環(huán)境中與全局變量互換使用。
var color = "blue"; function changeColor() { var anotherColor = "red"; function swapColors(){ //這里可以訪問color、anotherColor和tempColor var tempColor = anotherColor; anotherColor = color; color = tempColor; } //這里可以訪問color和anotherColor,但不能訪問tempColor swapColors(); } //這里只能訪問color changeColor();
以上代碼,涉及3個執(zhí)行環(huán)境:
全局環(huán)境(在web瀏覽器中就是window)
函數(shù)changeColor()的局部環(huán)境
函數(shù)swapColors()的局部局部
全局環(huán)境中有一個變量color和一個函數(shù)changeColor()。changeColor()的局部環(huán)境中有一個名為anotherColor的變量和一個名為swapColors()的函數(shù),但它也可以訪問全局環(huán)境中的變量color。swapColors()的局部環(huán)境中有一個變量tempColor,該變量只能在這個環(huán)境中訪問到。
無論全局環(huán)境還是changeColor()的局部環(huán)境都無權(quán)訪問tempColor。
然而,在swapColors()內(nèi)部,則可以訪問其他兩個環(huán)境中的變量,因為那兩個環(huán)境是它的父執(zhí)行環(huán)境。
window, color, changeColor() | anotherColor, swapColors() | tempColor
內(nèi)部環(huán)境可以通過作用域鏈訪問所有的外部環(huán)境,但外部環(huán)境不能訪問內(nèi)部環(huán)境中的任何變量和函數(shù)。
這些環(huán)境之間的聯(lián)系是線性、有次序的。
每個環(huán)境都可以向上搜索作用域鏈,以查詢變量和函數(shù)名。但是,任何環(huán)境都不能通過向下搜索作用域鏈而進(jìn)入另一個執(zhí)行環(huán)境。
函數(shù)參數(shù)也被當(dāng)做變量來對待,因此其訪問規(guī)則與執(zhí)行環(huán)境中的其他變量相同。
JavaScript沒有塊級作用域經(jīng)常會導(dǎo)致理解上的困惑。
在其他類C的語言中,由花括號封閉的代碼塊都有自己的作用域(如果用ECMAScript的話來講,就是它們自己的執(zhí)行環(huán)境),因而支持根據(jù)條件來定義變量。
if(true) { var color = "blue"; } console.log(color); //"blue"
這里是在有一個if語句中定義了變量color。
如果是在C、C++或Java中,color會在if語句執(zhí)行完畢后被銷毀。
但在JavaScript中,if語句中的變量聲明會將變量添加當(dāng)前的執(zhí)行環(huán)境(在這里是全局環(huán)境window)中。
在使用for語句時尤其要牢記這一差異。
for(var i = 0; i < 10; i++) { console.log(i); // 0,1,2,3,4,5,6,7,8,9 } /* //等價于 var i; for(i = 0; i < 10; i++) { console.log(i); } */ console.log(i); //10
對于有塊級作用域的語言來說,for語句初始化變量的表達(dá)式所定義的變量,只會存在于循壞的環(huán)境之中。而對于JavaScript來說,由for語句創(chuàng)建的變量i即使在for循環(huán)結(jié)束之后,也依舊會存在于循壞外部的執(zhí)行環(huán)境中。
使用var聲明的變量會自動被添加到最接近的環(huán)境中,在函數(shù)內(nèi)部,最接近的環(huán)境就是函數(shù)的局部環(huán)境。
如果初始化變量時沒有使用var聲明,該變量會自動被添加到全局作用域。
function add(num1, num2) { var sum = num1 + num2; return sum; } var result = add(10,20); //30 console.log(sum); //sum is not defined
以上代碼中的函數(shù)add()定義了一個名為sum的局部變量,該變量包含加法操作的結(jié)果。
雖然結(jié)果值從函數(shù)中返回了,但變量sum在函數(shù)外部是訪問不到的。
如果省略這個例子中的var關(guān)鍵字,那么當(dāng)add()執(zhí)行完畢后,sum也將可以訪問到。
function add(num1, num2) { sum = num1 + num2; return sum; } var result = add(10,20); // 30 console.log(sum); 30
在這個例子中的變量sum在被初始化賦值時沒有使用var關(guān)鍵字。
于是,當(dāng)調(diào)用完add()之后,添加到全局環(huán)境中的變量sum將繼續(xù)存在。
即使函數(shù)已經(jīng)執(zhí)行完畢,后面的代碼依舊可以訪問它。
在編寫JavaScript代碼的過程中,不聲明而直接初始化變量時一個常見的錯誤,這樣會導(dǎo)致一些不可預(yù)估的意外。養(yǎng)成良好的習(xí)慣,在初始化變量之前,一定要先聲明,這樣就可以避免類似問題。在嚴(yán)格模式下,初始化未經(jīng)聲明的變量會導(dǎo)致錯誤。
當(dāng)在某個環(huán)境中為了讀取或?qū)懭攵靡粋€標(biāo)識符時,必須通過搜索來確定該標(biāo)識符實際代表什么。搜索過程從作用域鏈的前端開始,向上逐級查詢與給定名字匹配的標(biāo)識符。
如果在局部環(huán)境中找到了該標(biāo)識符,搜索過程停止,變量就緒。
如果在局部環(huán)境中沒有找到該變量,則繼續(xù)沿作用域向上搜索。
搜索過程將一直追溯到全局環(huán)境的變量對象。
如果在全局環(huán)境中也沒有找到這個標(biāo)識符,則意味著該變量尚未聲明。
var color = "blue"; function getColor() { return color; } console.log(getColor()); // "blue" /* window = { color, getColor = function() { return color; } } */
調(diào)用本例中的函數(shù)getColor()時會引用變量color。
為了確定變量color的值,將開始一個兩步的搜索過程。
首先,在getColor()的局部環(huán)境中搜索變量對象,查找其中是否包含一個名為color的標(biāo)識符。
然后,沒有找到,對不?那就到外面的環(huán)境中找,在全局作用域中找到名為color的標(biāo)識符。
搜索到了定義這個變量的變量對象,搜索過程宣告結(jié)束。
在這個搜索過程中,如果存在一個局部的變量的定義,則搜索會自動停止(找到了,我就不找了),不再進(jìn)入另一個變量對象。換句話說,如果局部環(huán)境中存在著同名標(biāo)識符,就不會使用位于父環(huán)境中的標(biāo)識符。
var color = "blue"; function getColor() { var color = "red"; return color; } console.log(getColor()); //"red"
修改后的代碼在getColor()函數(shù)中聲明了一個名為color的局部變量。
調(diào)用函數(shù)時,該變量就會被聲明。而當(dāng)函數(shù)中的第二行代碼執(zhí)行時,意味著必須找到并返回變量color的值。
搜索過程,首先從局部環(huán)境中開始,而且在這里發(fā)現(xiàn)了一個名為color的變量,其值為“red”。
變量已經(jīng)在函數(shù)的局部環(huán)境中找到了,所以搜索停止,return語句就使用這個局部變量,并為函數(shù)返回“red”。
如果不使用window.color都無法訪問全局color變量。
變量查詢也不是沒有代價的。很明顯,訪問局部變量要比訪問全局變量更快,因為不用向上搜索作用域鏈。JavaScript引擎在優(yōu)化標(biāo)識符查詢方面做得不錯,因此這個差別在將來恐怕可以忽略不記。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享ES5中執(zhí)行環(huán)境和作用域的詳細(xì)介紹(代碼示例)內(nèi)容對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來學(xué)習(xí)!
本文題目:ES5中執(zhí)行環(huán)境和作用域的詳細(xì)介紹(代碼示例)
網(wǎng)站網(wǎng)址:http://jinyejixie.com/article46/gcehhg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、做網(wǎng)站、手機網(wǎng)站建設(shè)、網(wǎng)站導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)