function test() { console.log(a); // undefined console.log(foo()); // 2 var a = 1; function foo() { return 2; }; }; test();
不是很準確的草圖,大概瞭解就好。數組
建立階段:
在這個階段中,執行上下文分別會建立變量對象、創建做用域鏈,以及肯定this的指向。瀏覽器
代碼執行階段:
建立完成後,就會開始執行代碼,這個時候,會完成變量賦值,函數引用,以及執行其餘代碼。函數
變量對象的建立,經歷如下過程。測試
創建arguments對象。檢查上下文中的參數,創建該對象下的屬性與屬性值(key-value)this
檢查當前上下文的函數聲明,也就是使用function關鍵字聲明的函數。在變量對象中以函數名創建一個屬性,屬性值爲指向該函數所在內存地址的引用。若是函數名的屬性已經存在,那麼該屬性將會被新的引用所覆蓋。spa
檢查當前上下文中的變量聲明,每找到一個變量聲明,就在變量對象中以變量名創建一個屬性,屬性值爲undefined。若是該變量名的屬性已經存在,爲了防止同名的函數被修改成undefined,則會直接跳過,原屬性值不會被修改。指針
因此,因而就有了圖中的VO引用的對象的圖示,這就是變量提高的真正緣由,對於函數聲明,它的優先級是大於變量聲明的,因此在建立階段,函數聲明的函數名就持有了函數的引用。而變量賦值須要在後面的執行階段才被賦值。code
未進入執行階段前,變量對象中的屬性都不能被訪問!可是進入執行階段以後,變量對象轉變爲了活動對象(Active Object),裏面的屬性都能被訪問了,而後開始進行執行階段的操做。對象
目前個人測試:blog
函數內設有形參,可是不傳實參,遍歷arguments對象時沒有任何值
函數內不設形參,可是傳實參,遍歷arguments對象有值對應的索引
function test(a,b,c,d) { for (var i in arguments) { console.log(i); } console.log(arguments.length+"個"); }; test(1,2,3,4); // 0 1 2 3 // "4個" function test2(a,b,c,d) { for (var i in arguments) { document.write(i+"<br />") } document.write(arguments.length+"個"); }; test2(); // 什麼也沒有 // 0個
腦子裏有這副圖後,咱們在來看另外一個栗子:
function test() { console.log(foo()); console.log(bar); var foo = "Hello"; console.log(foo); var bar = function () { return "world"; }; function foo() { return "hello"; }; }; test(); // "hello" // "undefined" // "Hello"
主要討論同變量聲明與同變量聲明與函數聲明的狀況,這也是變量對象在建立時所作的工做;
檢查當前上下文的函數聲明,也就是使用
function
關鍵字聲明的函數。在變量對象中以函數名創建一個屬性,屬性值爲指向該函數所在內存地址的引用。若是函數名的屬性已經存在,那麼該屬性將會被新的引用所覆蓋。檢查當前上下文中的變量聲明,每找到一個變量聲明,就在變量對象中以變量名創建一個屬性,屬性值爲
undefined
。若是該變量名的屬性已經存在,爲了防止同名的函數被修改成undefined
,則會直接跳過,原屬性值不會被修改。
如代碼中的foo
,在test
函數的執行上下文建立變量對象後,建立階段,foo
就是變量對象中的的鍵名(Key),而鍵值就是函數的地址指針,由於函數聲明的優先級大於變量聲明,因此foo
此時就持有了函數的引用,而var foo
的變量聲明就被跳過。
執行階段,進行賦值操做,foo
被從新賦值"Hello"
,同時變量bar
從未賦值(undefined
)到持有一個函數的引用,這就是變量對象=>活動對象,執行棧,執行上下文所發生的操做。
var globla = 10; function test() { return globla++; }; test();
// 以瀏覽器中爲例,全局對象爲window // 全局上下文 windowEC = { VO: window, scopeChain: {}, this: window }
以瀏覽器中爲例,全局對象爲window
。
全局上下文有一個特殊的地方,它的變量對象,就是window
對象。而這個特殊,在this
指向上也一樣適用,this
也是指向window
。除此以外,全局上下文的生命週期,與程序的生命週期一致,只要程序運行不結束,好比關掉瀏覽器窗口,全局上下文就會一直存在。其餘全部的上下文環境,都能直接訪問全局上下文的屬性。