JavaScript的預編譯過程
阿新 • • 發佈:2019-01-31
JavaScript在執行時,要經歷三步
1. 語法分析 2.預編譯 3.解析執行(自上而下)
JavaScript預編譯
先思考這麼一個題
function fn (a) {
console.log(a);
var a = 123;
console.log(a);
function a(){};
console.log(a);
var b =function (){};
console.log(b);
}
fn(1);
預編譯四部曲
- 建立AO物件 Activation Object(執行期上下文)
- 找形參和變數宣告,將變數和形參名作為AO屬性名,值為undefined
- 將實參值和形參統一
- 在函式體裡面找函式宣告,值賦予函式體
這四步的權重比4>3>2>1,也就是一個覆蓋的過程.
函式宣告在變數宣告的前面
函式宣告才存在變數提升。即
function a(){};
,而var b =function (){};
不會提升。
詳細分析
先看一個面試中常遇到的問題
console.log(a); // function a(){}
var a = 1;
function a(){};
逐行執行,在AO中是:
AO{
a: undefied
}
AO{
a: function(){}
}
換一換
var a = 1;
console.log(a); // 1
function a(){};
逐行執行,在AO中是:
AO{
a: undefied
}
AO{
a: function(){}
}
// js是自上而下執行的,先執行var a = 1; 所有AO中的a就被覆蓋
AO{
a: 1
}
按步驟分析文章開頭的例子
- 第一步
AO{
}
- 第二步
AO{
a: undefined,
b: undefined
}
- 第三步
AO{
a: 1,
b: undefined
}
- 第四步
AO{
a: function a(){},
b: undefined
}
解釋執行
執行的時候:
AO{
a: function a(){},
b: undefined
}
// a = 123;
AO{
a: 123,
b: undefined
}
結果:
function fn (a) {
console.log(a); // function(){}
var a = 123;
console.log(a); // 123
function a(){};
console.log(a); // 123
var b =function (){};
console.log(b); // function(){}
}
fn(1);
加入window,全域性環境
global = 100;
function fn() {
console.log(global);
global = 200;
console.log(global);
var global = 300;
}
fn();
var global;
在全域性環境中會生成一個 GO物件 (Global Object),還是按照上面的四步執行。
GO {
global: undefined
}
// 執行到 global = 100
:
GO {
global: 100
}
當執行fn
之前會先生成一個AO:
AO {
global: undefined
}
所以第一次列印global
是undefined
。
這個時候雖然全域性變數中的
global
已經是100
,但是fn
函式中自己有global
變數,所以不會引用全域性中的。
當執行到global = 200
:
AO {
global: 200
}
所以第二次列印global
是200
最後思考一個問題
function fn(){
var a = b = 100;
console.log(window.a);
console.log(window.b);
}
var a = b =100;
先將100賦值給b,即b=100,此時b沒有宣告就被賦值,在JavaScript中如果一個變數未宣告就直接賦值,那麼這個變數就是個全域性變數。