摘要:所以,全局執行環境的變量對象始終都是作用域鏈中的最后一個對象。搜索過程從作用域鏈的最前端開始,逐級向后回溯,直到找到標識符為止。查詢標識符搜索過程就是沿作用域鏈向上查詢的過程。
執行環境
執行環境就是“環境”,是js中最重要的概念。執行環境定義了變量或函數有權訪問的其他數據。每個執行環境都有一個與之相關的變量對象(我們編寫的代碼無法訪問這個對象)。
全局執行環境(是最外圍的執行環境。在Web瀏覽器中,全局執行環境是Window對象。某個執行環境中的所有代碼執行完畢后,該環境會被銷毀;全局執行環境則直到應用程序退出,如關閉網頁或瀏覽器時才會被銷毀。環境被銷毀時,保存在其中的所有變量和函數定義也都會被銷毀。)
執行環境(當執行流進入一個函數時,函數的環境會被推入一個環境棧中。當函數執行之后,環境棧將其彈出,把控制權返回給之前的執行環境。)
作用域鏈(當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈。其用途是保證對執行環境有權訪問的所有變量和函數的有序訪問。一個包含環境的變量對象到另一個包含環境的變量對象,最后到全局執行環境的變量對象。所以,全局執行環境的變量對象始終都是作用域鏈中的最后一個對象。)
標識符解析標識符解析是沿著作用域鏈一級一級地搜索標識符的過程。搜索過程從作用域鏈的最前端開始,逐級向后回溯,直到找到標識符為止。如:
var color = "blue"; function changeColor(){ if (color === "blue"){ color = "red"; }else { color = "blue"; } } changeColor(); document.write("Color is now " + color);
在上面的例子中,函數changeColor()的作用域鏈包含兩個對象:changeColor()函數自己的變量對象和全局環境的變量對象。(可以在函數內部訪問變量color,就是因為可以在這個作用域鏈中找到它。)在看另一個例子:
var color = "blue"; function changeColor(){ var anotherColor = "red"; function swapColors(){ var tempColor = anotherColor; anotherColor = color; color = tempColor; //這里可以訪問tempColor anotherColor color } //這里可以訪問anotherColor color } //這里可以訪問color changeColor();
執行環境:3個,全局環境,changeColor()的局部環境和swapColors()的局部環境。
全局環境:一個變量color 和一個函數changeColor()。
changeColor()環境:一個變量anotherColor 和一個swapColors()函數。(可以訪問全局變量中的color)
swapColors()環境:一個變量tempColor。(可以訪問全局環境中的color 和changeColor()環境中的anotherColor變量。)
swapColors()內部可以訪問到其他兩個環境中的所有變量,因為其他兩個環境是它的父執行環境*
上面的例子可以用作用域鏈表示出來:(話說有沒有網友可以推薦下好用的圖床呀?純文本畫畫還真麻煩。)
window(全局環境) | |-color(變量) | |-changeColor()(局部環境) | |-anotherColor(變量) | |-swapColors()(局部環境) | |-tempColor(變量)
內部環境可以通過作用連訪問所有的外部環境,但外部環境不能訪問內部環境的任何變量和函數。就是說,每個環境都可以向上搜索作用域鏈,但任何環境都不能向下搜索作用域鏈。
延長作用域鏈雖然執行環境的類型總共只有全局和局部(函數)兩種,但是還是可以使用下面兩種辦法來延長作用域鏈。
try-catch 語句的catch 塊;
with 語句
上面這種方法就是當執行流進入下列任何一個語句時,作用域鏈就會得到加長。如:
function log(){ var string = "the location is: " with(location){ var url = string + href; } return url; } document.write(log()); //the location is: ... Volumes/TOSHIBA/project/tester/repetition.html
這里面使用with 語句,可以看到return url 語句可以訪問到with 語句中的url 變量。再看下面的例子:
function log(){ var string = "the location is: " function href(){ var url = string + location.href; } return url; } document.write(log()); // ReferenceError: Can"t find variable: url
如果是普通的function 函數則不能訪問url 變量。
另外,在IE8 中,即使是在catch 塊的外部也可以訪問到錯誤對象。IE9 修復了這個問題。
沒有塊級作用域JavaScript 不像C 語言中,由花括號封閉的代碼塊都有自己的作用域。JavaScript 沒有塊級作用域。如:
if (true){ var color = "blue"; } document.write(color); //"blue"
花括號以外的地方仍然可以訪問話括號內的變量。
尤其應該在for 循環中注意這個特性:
for (var i = 0; i < 5; i ++){ var count = i + i; } document.write(count); //8聲明變量
如果初始化變量時沒有使用var 聲明,該變量會被添加到全局環境中去。如:
function count(x,y){ var result = x + y; } count(1,2); document.write(result); // ReferenceError: Can"t find variable: result function count(x,y){ result = x + y; } count(1,2); document.write(result); //3
在編寫代碼的過程中,不聲明而直接初始化變量是一個常見的錯誤做法。很可能會導致以外。建議在初始化變量之前,一定要先聲明。在嚴格模式下,初始化未經聲明的變量會導致錯誤。
查詢標識符搜索過程就是沿作用域鏈向上查詢的過程。如:
var result = 1; function func(){ document.write(result); } func(); //1
如果局部環境中存在著同名標識符,就不會使用位于父環境中的標識符。如:
var result = 2; function func(){ var result = 1; document.write(result); } func(); //1 document.write(window.result); //2 或者直接用下面的代碼返回最初的result document.write(result);
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86162.html
摘要:深入理解原型和閉包王福朋博客園深入理解原型和閉包一切都是對象原文鏈接本文要點一切引用類型都是對象,對象是屬性的集合。每個對象都有一個,可稱為隱式原型。另外注意,構造函數的函數名第一個字母大寫規則約定。 深入理解javascript原型和閉包 王福朋 - 博客園 —— 《 深入理解javascript原型和閉包》 1. 一切都是對象 原文鏈接:http://www.cnblogs.com...
摘要:類型每個函數都是類型的實例。如以上代碼可行,是因為在代碼開始值錢,解析器就已經通過一個名為函數聲明提升的過程,讀取并將函數聲明添加到執行環境中去。也可同時使用函數聲明和函數表達式,但在瀏覽器中會出錯。 Function 類型 每個函數都是Function 類型的實例。函數名實際上就是一個指向函數對象的指針,不會與某個函數綁定。 函數聲明方式創建Function,語法如下: functi...
摘要:如他返回的對象是。方法,這個方法用于確定文檔是否獲得了焦點。另外,需要注意的是,該屬性插入元素并不會執行其中的腳本。在中,方法接收一個字符串,返回一個經過無害處理后的版本。屬性同樣的,在讀模式下返回調用它的元素及所有子節點的標簽。 與類相關的擴充 getElementsByClassName()方法 接收一個參數,即一個或多個類名的字符串。如: console.log(documen...
閱讀 1010·2021-11-22 13:52
閱讀 924·2019-08-30 15:44
閱讀 570·2019-08-30 15:43
閱讀 2424·2019-08-30 12:52
閱讀 3473·2019-08-29 16:16
閱讀 637·2019-08-29 13:05
閱讀 2943·2019-08-26 18:36
閱讀 1975·2019-08-26 13:46