了解js面向?qū)ο缶幊讨?,首先要了解js的執(zhí)行順序。js的解析過程分為兩個階段:預處理階段與執(zhí)行期。
預處理階段
在預處理階段,js會首先創(chuàng)建一個執(zhí)行上下文對象(Execute Context,然后掃描聲明式函數(shù)和用var定義的變量,將其加入執(zhí)行上下文環(huán)境中,看下面栗子:
var a = 5;
b = 1;
function f(){}
var g = function(){}
//執(zhí)行上下文對象
/*Execute Context{
a: undefined
f: 對函數(shù)的引用
}*/
從上面可以看出,js在預處理階段創(chuàng)建了一個預處理對象,將聲明式函數(shù)和var定義的變量放入其中,這里忽略了沒有用var聲明的b以及函數(shù)表達式 g。
alert(a); // undefined
alert(b); // 報錯 b in not defined
alert(c); // 函數(shù)體被打印出來
alert(d); // 報錯
var a = 1;
b = 5;
function c(){
console.log('c');
}
var d = function(){
console.log('d');
}
從上面例子的輸出結(jié)果就可以看出js預處理階段做了哪些事情,對于沒有加進函數(shù)變量預處理階段的變量或函數(shù),會直接報錯。
對于沖突解決有兩種情況:
- 處理函數(shù)聲明有沖突時,會覆蓋前面
- 處理函數(shù)變量聲明有沖突時,會直接忽略
alert(f); // 彈出function f(){console.log('fff');}
function f(){
console.log('ff');
}
var f = 10;
function f(){
console.log('fff');
}
總結(jié)一句話:函數(shù)是js里的第一等公民。
執(zhí)行階段
在執(zhí)行階段中,js會先掃描函數(shù)聲明后掃描變量,然后給預處理階段中執(zhí)行上下文對象中的成員賦值,如果沒有用var聲明的變量,會成為外部執(zhí)行上下文的成員。
alert(a);
alert(f);
var a = 1;
function f(){}
//在執(zhí)行階段的執(zhí)行上下文對象
/*{
a: 1; // 由undefined賦值為1
f: 指向?qū)瘮?shù)
}*/