JavaScript中,當調用一個函數時,就會有相應的一個執行環境被建立。而一個執行環境的生命週期包含兩個時期javascript
變量對象的建立,依次經歷瞭如下幾個過程。java
創建arguments對象。檢查當前上下文中的參數,創建該對象下的屬性與屬性值。瀏覽器
根據這個規則,理解變量提高就變得十分簡單了。在上面的規則中咱們看出,function聲明會比var聲明優先級更高一點。舉個例子:函數
function demo(){
console.log(a); //undefind testfn(); //11 var a = 2; function testfn() { console.log(11); } }
demo();
建立過程(EC:execution context)this
demoEC = {spa
VO: {},// 變量對象 對象
scopeChain: {},blog
this: {}生命週期
}ip
VO 爲 Variable Object的縮寫,即變量對象VO
VO= {
arguments: {...}, //注:在瀏覽器的展現中,函數的參數可能並非放在arguments對象中,這裏爲了方便理解
testfn: <foo reference>, // 表示foo的地址引用
a: undefined
}
未進入執行階段以前,變量對象中的屬性都不能訪問!可是進入執行階段以後,變量對象轉變爲了活動對象,裏面的屬性都能被訪問了,而後開始進行執行階段的操做。(PS:這裏能夠看出其實變量對象和活動對象實際上是指向同一個,只是處在執行環境不一樣生命週期)
當走到demo();時,進入執行階段
執行階段VO -> AO // Active ObjectAO
AO = {
arguments: {...},
foo: <foo reference>,
a: 1
}
所以,上面的例子demo,執行順序就變成了這樣
function demo() {
function testfn() {
console.log(1);
}
var a;
console.log(a);
a = 1;
}
demo() ;
function demo2() {
console.log(box);
console.log(car);
var car = "BWM";
console.log(car);
var box = function () {
console.log("box");
}
function car() {
console.log("carfn");
}
}
demo2();
建立階段VO
VO = {
arguments:{...},
car:<car refrence>, //這裏car不會被後來var car變量所覆蓋,而是直接跳過
box:undefind
}
當代碼走到demo2();時,VO>AO
AO = {
argument:{...},
car:"BWM",
box:<boxrefrence>
}
所以,demo2的執行順序就變成了這樣
function demo2() {
function car() {
console.log("carfn");
}
var box;
console.log(box); //undefind
console.log(car); //<car refrence>
car = "BWM";
console.log(car); //"BWM"
box = function() {
console.log("box");
}
}
demo() ;
以瀏覽器中爲例,全局對象爲window。
全局上下文有一個特殊的地方,它的變量對象,就是window對象。而這個特殊,在this指向上也一樣適用,this也是指向window。
windowEC = {
VO:window,
Scope chain:{},
this: window
}
除此以外,全局上下文的生命週期,與程序的生命週期一致,只要程序運行不結束,好比關掉瀏覽器窗口,全局上下文就會一直存在。其餘全部的上下文環境,都能直接訪問全局上下文的屬性。
參考連接:http://mp.weixin.qq.com/s/a_oWYwK0eI_74bMVoGLwCA