什么是預編譯茁帽?
前端同學都知道js里有個叫變量聲明提升的概念,其實這就是預編譯造成的吊输。預編譯也叫執(zhí)行期上下文铁追。當js代碼運行的時候,實際上是運行在執(zhí)行期上下文里面扭屁,執(zhí)行期上下文包含三種涩禀。
- 全局上下文(Global Object,即全局代碼,簡稱GO)
- 函數(shù)上下文 (Activation Object艾船,每個函數(shù)在運行的前一刻會創(chuàng)建屬于自己的執(zhí)行期上下文,簡稱AO)
- eval方法也會創(chuàng)建新的執(zhí)行期上下文 (用的不多屿岂,這里就不說它了)
var a = 1;
var b = 2;
function add(x,y) {
return x + y;
}
add(1,2)
// 1. 執(zhí)行代碼爷怀,首先創(chuàng)建一個全局的GO
// 2. 運行add函數(shù)的前一刻創(chuàng)建屬于add函數(shù)的AO
執(zhí)行期上下文棧
- 全局代碼執(zhí)行前,JS就會創(chuàng)建一個棧來儲存管理所有的執(zhí)行上下文對象
- 全局執(zhí)行期上下文確定后,把它添加到棧中(棧底)
- 當函數(shù)的執(zhí)行期上下文創(chuàng)建完后烤惊,把它添加到棧中(棧頂)
- 當前函數(shù)執(zhí)行完畢,在棧頂把這個函數(shù)的執(zhí)行期上下文移出
- 函數(shù)執(zhí)行中,遇到return直接終止可執(zhí)行的代碼,會直接將當前上下文彈出棧
- 全部代碼執(zhí)行完畢瘤缩,棧里就只剩全局的執(zhí)行期上下文了
- 當瀏覽器窗口關閉伦泥,移出全局的執(zhí)行期上下文
執(zhí)行期上下文創(chuàng)建過程
AO
- 創(chuàng)建AO對象(Activation Object)
- 找形參和變量聲明不脯,將變量和形參名作為 AO 屬性名,值為 undefined
- 將實參和形參相統(tǒng)一
- 在函數(shù)體里面找函數(shù)聲明防楷,值賦予函數(shù)體
function fn(a,b){
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b(){};
function d(){};
console.log(b);
}
fn(1,2)
/*
創(chuàng)建過程:
1. 創(chuàng)建AO對象
AO = {
}
2. 找形參和變量聲明复局,將變量和形參名作為 AO 屬性名,值為 undefined
AO = {
a:undedfined,
b:undefined,
c:undefined
}
3.將實參和形參相統(tǒng)一
AO = {
a:1,
b:2,
c:undefined
}
4. 在函數(shù)體里面找函數(shù)聲明峦剔,值賦予函數(shù)體
AO = {
a:1,
b:function b(){},
c:undefined,
d:function b(){}
}
*/
/*
函數(shù)執(zhí)行過程:
function fn(a,b){
console.log(a); // 1
c = 0; // AO的c變成0
var c; // AO創(chuàng)建過了角钩,忽略
a = 3; // AO的a變成3
b = 2; // AO的b變成2
console.log(b); // 2
function b(){}; // AO創(chuàng)建過了递礼,忽略
function d(){}; // AO創(chuàng)建過了,忽略
console.log(b); // 2
}
*/
GO
- 創(chuàng)建GO對象(Global Object)
- 找形參和變量聲明辫愉,將變量和形參名作為 GO 屬性名将硝,值為 undefined
- 在函數(shù)體里面找函數(shù)聲明,值賦予函數(shù)體
console.log(a)
var a= 1;
var b;
function c() {};
function b() {};
console.log(c)
console.log(b)
b = 2;
console.log(a)
console.log(b)
/*
創(chuàng)建過程:
1. 創(chuàng)建AO對象
AO = {
}
2. 找形參和變量聲明冀墨,將變量和形參名作為 AO 屬性名涛贯,值為 undefined
AO = {
a:undedfined,
b:undefined,
c:undefined
}
3. 在函數(shù)體里面找函數(shù)聲明蔚出,值賦予函數(shù)體
AO = {
a:undedfined,
b:function b(){},
c:function c(){},
}
*/
/*
函數(shù)執(zhí)行過程:
console.log(a) // undefined
var a= 1; // GO的a變成1
var b; // GO創(chuàng)建過了虫腋,忽略
function c(); // GO創(chuàng)建過了稀余,忽略
function b(); // GO創(chuàng)建過了,忽略
console.log(c) // function c() {}
console.log(b) // function b() {}
b = 2; // GO的b變成2
console.log(a) // 1
console.log(b) // 2
*/
其實全局對比函數(shù)的執(zhí)行期上下文創(chuàng)建過程就是少了個形參和實參統(tǒng)一盒蟆,其余的都一樣