1、JavaScript做用域javascript
1. 全局做用域(Global Scope)html
在代碼中任何地方都能訪問到的對象擁有全局做用域,通常來講如下幾種情形擁有全局做用域:前端
(1)最外層函數和在最外層函數外面定義的變量擁有全局做用域,例如:java
var authorName="山邊小溪"; function doSomething(){ var blogName="夢想天空"; function innerSay(){ alert(blogName); } innerSay(); } alert(authorName); //山邊小溪 alert(blogName); //腳本錯誤 doSomething(); //夢想天空 innerSay() //腳本錯誤
(2)全部末定義直接賦值的變量自動聲明爲擁有全局做用域,例如:函數
function doSomething(){ var authorName="山邊小溪"; blogName="夢想天空"; alert(authorName); } doSomething(); //山邊小溪 alert(blogName); //夢想天空 alert(authorName); //腳本錯誤
變量blogName擁有全局做用域,而authorName在函數外部沒法訪問到。this
(3)全部window對象的屬性擁有全局做用域spa
通常狀況下,window對象的內置屬性都擁有全局做用域,例如window.name、window.location、window.top等等。htm
2. 局部做用域(Local Scope) 對象
和全局做用域相反,局部做用域通常只在固定的代碼片斷內可訪問到,最多見的例如函數內部,全部在一些地方也會看到有人把這種做用域稱爲函數做用域,例以下列代碼中的blogName和函數innerSay都只擁有局部做用域。blog
function doSomething(){ var blogName="夢想天空"; function innerSay(){ alert(blogName); } innerSay(); } alert(blogName); //腳本錯誤 innerSay(); //腳本錯誤
2、做用域鏈(Scope Chain)
在JavaScript中,函數也是對象,實際上,JavaScript裏一切都是對象。函數對象和其它對象同樣,擁有能夠經過代碼訪問的屬性和一系列僅供JavaScript引擎訪的 內部屬性。其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被建立的做用域中對象的集合,這個集合被稱爲函數的做用域 鏈,它決定了哪些數據能被函數訪問。
當一個函數建立後,它的做用域鏈會被建立此函數的做用域中可訪問的數據對象填充。例如定義下面這樣一個函數:
function add(num1,num2) { var sum = num1 + num2; return sum; }
在函數add建立時,它的做用域鏈中會填入一個全局對象,該全局對象包含了全部全局變量,以下圖所示(注意:圖片只例舉了所有變量中的一部分):
函數add的做用域將會在執行時用到。例如執行以下代碼:
var total = add(5,10);
執行此函數時會建立一個稱爲「運行期上下文(execution context)」的內部對象,運行期上下文定義了函數執行時的環境。每一個運行期上下文都有本身的做用域鏈,用於標識符解析,當運行期上下文被建立時,而它的做用域鏈初始化爲當前運行函數的[[Scope]]所包含的對象。
這些值按照它們出如今函數中的順序被複制到運行期上下文的做用域鏈中。它們共同組成了一個新的對象,叫「活動對象(activation object)」,該對象包含了函數的全部局部變量、命名參數、參數集合以及this,而後此對象會被推入做用域鏈的前端,當運行期上下文被銷燬,活動對象也隨之銷燬。新的做用域鏈以下圖所示:
在函數執行過程當中,每遇到一個變量,都會經歷一次標識符解析過程以決定從哪裏獲取和存儲數據。該過程從做用域鏈頭部,也就是從活動對象開始搜索,查找同名的標識符,若是找到了就使用這個標識符對應的變量,若是沒找到繼續搜索做用域鏈中的下一個對象,若是搜索完全部對象都未找到,則認爲該標識符未定義。函數執行過程當中,每一個標識符都要經歷這樣的搜索過程。
轉自:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html