|
導讀網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立... 網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立在超文本基礎之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。 本篇文章給大家帶來的內容是關于ES5中執行環境和作用域的詳細介紹(代碼示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方一筆帶過,所以用自己所理解的,嘗試細致解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《JavaScript高級程序設計第三版》 執行環境(execution context)執行環境(execution context,為了簡單起見,有時也成為環境)是JavaScript中最為重要的一個概念。 執行環境,定義了變量或函數有權訪問其他數據,且決定了它們各自的行為。 每個執行環境都有一個與之關聯的變量對象(variable object),環境中定義的所有變量和函數都保存在這個對象中。 雖然我們編寫的代碼無法訪問這個對象,但解析器在處理數據時會在后臺使用它。 全局執行環境時最外圍的一個執行環境。 根據ECMAScript實現所在的宿主環境不同,表示執行環境的對象也不一樣。 在Web瀏覽器中,全局執行環境被認為是window對象,因此所有全局變量和函數都是作為window對象的屬性和方法創建的。 (變量的生命周期),某個執行環境中的所有代碼執行完畢后,該環境被銷毀,保存在其中的所有變量和函數定義也隨之銷毀) 全局執行環境直到應用程序退出——例如關閉網頁或瀏覽器時才會被銷毀。 每個函數都有自己的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。在函數執行之后,棧將其環境彈出,把控制權返回給之前的執行環境。ECMAScript程序中的執行流正是由這個方便的機制控制著。 作用域鏈(scope chain)當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈(scope chain)。 作用域鏈的前端,始終都是當前執行的代碼所在環境的變量對象。(也可以理解為“就近原則”)。 如果這個環境是函數,則將其活動對象(activation object)作為變量對象。 函數執行環境中的活動對象在最開始時,只包含一個變量,即arguments對象(這個對象在全局環境中是不存在的)作為變量對象。 作用域鏈中的下一個變量對象來自包含(外部)環境,而再下一個變量對象則來自下一個包含環境,這樣,一直延續到全局執行環境。 全局執行環境的變量對象,始終是作用域鏈中的最后一個對象。 標識符解析是沿著作用域鏈一級一級地搜索標識標識符的過程。 var color = "blue";
function changeColor() {
if(color === "blue") {
color = "red";
} else {
color = "blue";
}
}
changeColor();
console.log("Color is now " + color); // "color is now red"在這個簡單的例子中,函數changeColor()的作用域鏈包含兩個對象: 它自己的變量對象(其中定義著arguments對象)和全局環境的變量對象。 可以在函數內部訪問變量color,就是因為可以在這個作用域鏈中找到它。 此外,在局部作用中定義的變量可以在局部環境中與全局變量互換使用。 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個執行環境:
全局環境中有一個變量color和一個函數changeColor()。changeColor()的局部環境中有一個名為anotherColor的變量和一個名為swapColors()的函數,但它也可以訪問全局環境中的變量color。swapColors()的局部環境中有一個變量tempColor,該變量只能在這個環境中訪問到。 無論全局環境還是changeColor()的局部環境都無權訪問tempColor。 然而,在swapColors()內部,則可以訪問其他兩個環境中的變量,因為那兩個環境是它的父執行環境。
window, color, changeColor()
|
anotherColor, swapColors()
|
tempColor內部環境可以通過作用域鏈訪問所有的外部環境,但外部環境不能訪問內部環境中的任何變量和函數。 這些環境之間的聯系是線性、有次序的。 每個環境都可以向上搜索作用域鏈,以查詢變量和函數名。但是,任何環境都不能通過向下搜索作用域鏈而進入另一個執行環境。 函數參數也被當做變量來對待,因此其訪問規則與執行環境中的其他變量相同。 沒有塊級作用域(ES5中沒有)JavaScript沒有塊級作用域經常會導致理解上的困惑。 if(true) {
var color = "blue";
}
console.log(color); //"blue"這里是在有一個if語句中定義了變量color。 在使用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語句初始化變量的表達式所定義的變量,只會存在于循壞的環境之中。而對于JavaScript來說,由for語句創建的變量i即使在for循環結束之后,也依舊會存在于循壞外部的執行環境中。 聲明變量使用var聲明的變量會自動被添加到最接近的環境中,在函數內部,最接近的環境就是函數的局部環境。 如果初始化變量時沒有使用var聲明,該變量會自動被添加到全局作用域。 function add(num1, num2) {
var sum = num1 + num2;
return sum;
}
var result = add(10,20); //30
console.log(sum); //sum is not defined以上代碼中的函數add()定義了一個名為sum的局部變量,該變量包含加法操作的結果。 function add(num1, num2) {
sum = num1 + num2;
return sum;
}
var result = add(10,20); // 30
console.log(sum); 30在這個例子中的變量sum在被初始化賦值時沒有使用var關鍵字。 在編寫JavaScript代碼的過程中,不聲明而直接初始化變量時一個常見的錯誤,這樣會導致一些不可預估的意外。養成良好的習慣,在初始化變量之前,一定要先聲明,這樣就可以避免類似問題。在嚴格模式下,初始化未經聲明的變量會導致錯誤。 2.查詢標識符當在某個環境中為了讀取或寫入而引用一個標識符時,必須通過搜索來確定該標識符實際代表什么。搜索過程從作用域鏈的前端開始,向上逐級查詢與給定名字匹配的標識符。 如果在局部環境中找到了該標識符,搜索過程停止,變量就緒。 如果在局部環境中沒有找到該變量,則繼續沿作用域向上搜索。 搜索過程將一直追溯到全局環境的變量對象。 如果在全局環境中也沒有找到這個標識符,則意味著該變量尚未聲明。 var color = "blue";
function getColor() {
return color;
}
console.log(getColor()); // "blue"
/*
window = {
color,
getColor = function() {
return color;
}
}
*/調用本例中的函數getColor()時會引用變量color。 為了確定變量color的值,將開始一個兩步的搜索過程。
搜索到了定義這個變量的變量對象,搜索過程宣告結束。 在這個搜索過程中,如果存在一個局部的變量的定義,則搜索會自動停止(找到了,我就不找了),不再進入另一個變量對象。換句話說,如果局部環境中存在著同名標識符,就不會使用位于父環境中的標識符。 var color = "blue";
function getColor() {
var color = "red";
return color;
}
console.log(getColor()); //"red"修改后的代碼在getColor()函數中聲明了一個名為color的局部變量。 如果不使用window.color都無法訪問全局color變量。 變量查詢也不是沒有代價的。很明顯,訪問局部變量要比訪問全局變量更快,因為不用向上搜索作用域鏈。JavaScript引擎在優化標識符查詢方面做得不錯,因此這個差別在將來恐怕可以忽略不記。 但是,我們還是要養成良好的編程習慣。雖說,這個差別可以忽略不記。 以上就是ES5中執行環境和作用域的詳細介紹(代碼示例)的詳細內容,更多請關注php中文網其它相關文章! 網站建設是一個廣義的術語,涵蓋了許多不同的技能和學科中所使用的生產和維護的網站。 |
溫馨提示:喜歡本站的話,請收藏一下本站!