JavaScript是解釋型語言,會先預編譯,然後執行,在執行過程中順序執行。
因此在JS中存在變量提升的現象
在函數中預編譯執行步驟:
- 創建空AO對象,(Activity Object)執行期上下文
- 尋找函數的
形參
和變量聲明
,將變量和形參作爲AO對象的屬性名,值爲undefined - 將形參和實參相統一,將undefined更改爲具體實參值。
- 尋找函數中的
函數聲明
,將函數名作爲AO屬性名,值爲函數體 - 預編譯環節結束
- 執行,不斷更新AO對象
- 執行完畢,AO對象銷燬
全局對象GO也是一樣
實例一
function fn(a){
console.log(a)
var a = 123
console.log(a)
function a(){}
console.log(a)
var b = function(){}
console.log(b)
function d(){}
}
- 創建空AO對象
AO{
// 空對象
}
- 尋找函數形參和變量聲明
AO{
a: undefined,
b: undefined,
}
- 將形參和實參相統一
AO{
a: 1,
b: undefined
}
- 函數聲明
AO{
a: function a(){},
b: undefined,
d: function d(){},
}
預編譯環節結束,AO對象更新爲
AO{
a: function a(){},
b: undefined,
d: function d(){},
}
函數開始順序執行
function fn(a){
console.log(a); // function a(){}
var a = 123 // 對a賦值,AO對象改變
console.log(a) // 123
function a(){} // 預編譯環節進行變量提升,執行時不看此行代碼
console.log(a) // 123
var b = function(){} // 函數聲明,對b重新賦值,AO對象改變
console.log(b) // function b(){}
function d(){} // 預編譯環節變量提升,執行時不再看此行代碼
}
實例二
function test(a,b){
console.log(a); // 1
c = 0; // AO更新
var c; // 預編譯,不看
a = 3; // AO更新
b = 2; // AO更新
console.log(b); // 2
function b(){}; // 預編譯,不看
function d(){}; // 預編譯,不看
console.log(b); // 2
}
test(1); // 1 2 2
/**
AO1{}
AO2{
a: undefined,
b: undefined,
c: undefined,
}
AO3{
a: 1,
b: undefined,
c: undefined,
}
AO4{
a: 1,
b: function a(){},
c: undefined,
d: function c(){},
}
end;
**/
實例三
// 引入GO(全局對象)
console.log(test); // function test(test){,,,,,}
function test(test){
console.log(test); // function test(){}
var test = 234; // AO改變
console.log(test); // 234
function test(){} // 預編譯,不看
}
test(1);
var test = 123;
執行結果:
// function test(test){,,,,,}
// function test(){}
// 234
解析過程:
/**
頁面加載完成,生成GO對象
GO1{
test: undefined
}
GO2{
test: function(test){xxxxx}
}
執行test()錢生成AO對象
AO1{
test: undefined,
}
AO2{
test: 1
}
AO3{
test: function test(){}
}
預編譯結束,開始執行
AO4{
test: 234
}
**/
實例四
function demo(){
console.log(b); // undefined
if(a){
var b = 100;
}
console.log(b); // undefined
c = 234; // 全局變量
console.log(c); // 234
}
var a;
demo();
a = 10;
console.logs(c); // 234
// undefined undefined 234 234
/*
GO1{
a: undefined
}
GO2{
a: undefined,
demo: function demo(){xxxxx},
}
執行demo函數前預編譯,由於c未聲明就使用,所以是全局變量
GO2{
a: undefined,
demo: function demo(){xxxxx},
c: undefined
}
a是undefined,if裏不執行
輸出undefined
GO4{
a : undefined,
demo : function demo(){}
c : 234;
}
//輸出234
GO5{
a : 10,
demo : function demo(){}
c : 234;
}
//輸出234
*/