變量對象的創(chuàng)建,依次經(jīng)歷了以下幾個過程。
- 建立arguments對象玖绿。檢查當(dāng)前上下文中的參數(shù),建立該對象下的屬性與屬性值叁巨。
- 檢查當(dāng)前上下文的函數(shù)聲明斑匪,也就是使用function關(guān)鍵字聲明的函數(shù)。在變量對象中以函數(shù)名建立一個屬性锋勺,屬性值為指向該函數(shù)所在內(nèi)存地址的引用蚀瘸。如果函數(shù)名的屬性已經(jīng)存在狡蝶,那么該屬性將會被新的引用所覆蓋。
- 檢查當(dāng)前上下文中的變量聲明贮勃,每找到一個變量聲明贪惹,就在變量對象中以變量名建立一個屬性,屬性值為undefined寂嘉。如果該變量名的屬性已經(jīng)存在奏瞬,為了防止同名的函數(shù)被修改為undefined,則會直接跳過泉孩,原屬性值不會被修改硼端。
demo1:
console.log(testOne); // function testOne() { console.log('testOne') }
function testOne() { console.log('testOne') }
var testOne = 100;
console.log(testOne); // 100
執(zhí)行過程:
// 首先將所有函數(shù)聲明放入變量對象中
function testOne() { console.log('testOne') }
// 其次將所有變量聲明放入變量對象中,但是因為testOne已經(jīng)存在同名函數(shù)寓搬,因此此時會跳過undefined的賦值
// var testOne;
// 然后開始執(zhí)行階段代碼的執(zhí)行
console.log(testOne); // function testOne() { console.log('testOne') }
testOne= 100;
console.log(testOne); // 100
demo2:
function testTwo() {
console.log(a);//undefined
console.log(foo());//2
var a = 1;
function foo() {
return 2;
}
}
testTwo();
//上述代碼執(zhí)行順序
function testTwo() {
function foo() {
return 2;
}
var a;
console.log(a);
console.log(foo());
a = 1;
}
testTwo();
demo3:
function testTree() {
console.log(foo);//function foo() { return 'hello'; }
console.log(bar);//undefined
var foo = 'Hello';
console.log(foo);//Hello
var bar = function () {
return 'world';
}
console.log(bar);//function () {return 'world';}
function foo() {
return 'hello';
}
}
testTree();
//上述代碼執(zhí)行順序
function testTree() {
function foo() {
return 'hello';
}
var foo,bar;
console.log(foo);
console.log(bar);
foo = 'Hello';
bar = function () {
return 'world';
}
console.log(foo);
console.log(bar);
}
testTree();