文章目錄
JavaScript運行三部曲
JavaScript預(yù)編譯
01 關(guān)于預(yù)編譯的一些知識點
02 預(yù)編譯四部曲(局部)
1. 創(chuàng)建AO對象(Activation Object) (執(zhí)行期上下文)
2. 找形參和變量聲明禾乘,將變量和形參名作為AO屬性名,值為undefined
3. 將實參值和形參統(tǒng)一 (全局預(yù)編譯省略這一步)
4. 在函數(shù)體里面找函數(shù)聲明璧诵,值賦予函數(shù)體
03 綜合例題------全局和局部的預(yù)編譯和解釋執(zhí)行過程
1. 全局預(yù)編譯三部曲
2. 局部預(yù)編譯四部曲
3. JavaScript的解釋執(zhí)行
JavaScript運行三部曲
在學(xué)習(xí)預(yù)編譯之前,我們要先了解一下js的運行步驟:
語法分析:通篇檢查代碼是否有語法錯誤,若有晌姚,則程序不會執(zhí)行屿储;若無鹊奖,則進行預(yù)編譯店展。
預(yù)編譯
解釋執(zhí)行:從上到下依次執(zhí)行函數(shù)代碼养篓。
JavaScript預(yù)編譯
01 關(guān)于預(yù)編譯的一些知識點
(1)函數(shù)聲明整體提升:不管你的函數(shù)聲明寫在哪里,系統(tǒng)總是會將其提升到邏輯最前面壁查,所以不管你是在函數(shù)的上面或下面調(diào)用函數(shù),其實都是在下面調(diào)用的剔应。(2)變量僅聲明提升:如 var a = 123;則將其拆成兩個部分 即 聲明var a位置提升到邏輯最前端睡腿,賦值a=123不提升。所以若是在聲明賦值變量前進行調(diào)用峻贮,則會顯示undefined席怪,而不會報錯。(3)imply global 暗示全局變量:即任何變量纤控,如果變量未經(jīng)聲明就賦值挂捻,此變量就為全局對象所有。即:
function test(){
a = 10; //在局部里面賦值船万,沒有進行var聲明
}
因為沒有進行var聲明刻撒,相當(dāng)于在全局域里定義,即window.a = 10;
var a = b = 123;//局部里
上面代碼的執(zhí)行順序:先將123賦給b耿导,其次是b的值賦給a声怔,但是聲明只聲明了a,沒有聲明b舱呻,所以此時b歸window所有醋火。
(4)一切聲明的全局變量,全是window的屬性,即歸window所有芥驳,而調(diào)用全局變量柿冲,其實就是調(diào)用window.變量。(window 就是全局的域)即:
var b = 234; //在全局域里面聲明定義
即 相當(dāng)于window.b = 234兆旬。
02 預(yù)編譯四部曲(局部)
下面就通過check這個函數(shù)來解釋預(yù)編譯的四個步驟
function check(a) {
console.log(a);
var a = 123; //變量聲明和定義
console.log(a);
function a() {} //函數(shù)聲明
console.log(a);
var b = function () {} //變量聲明和定義
console.log(b);
function d() {} //函數(shù)聲明
}
check(1);
1. 創(chuàng)建AO對象(Activation Object) (執(zhí)行期上下文)
? AO {}
2. 找形參和變量聲明假抄,將變量和形參名作為AO屬性名,值為undefined
從上面的代碼中爵憎,我們可以知道形參是a慨亲,也定義了變量b。
AO {
a : undefined,
b : undefined,
}
3. 將實參值和形參統(tǒng)一 (全局預(yù)編譯省略這一步)
函數(shù)執(zhí)行傳入的實參是1宝鼓,所以形參a=1刑棵。
AO {
a : 1,
b : undefined,
}
4. 在函數(shù)體里面找函數(shù)聲明,值賦予函數(shù)體
a的值變成了函數(shù)體(存在同名的情況愚铡,直接覆蓋以前的值)蛉签,還添加了一個d屬性,值為函數(shù)體沥寥。
AO {
a : function a() {},
b : undefined,
d : function d() {}
}
以上預(yù)編譯過程就結(jié)束了碍舍,接下來就是js三步曲中的第三步------解釋執(zhí)行。(解釋執(zhí)行的時候邑雅,AO對象里的屬性值也會發(fā)生改變片橡,而每次想要輸出的變量,其實就是在AO對象中找對應(yīng)的值)
//開始js的解釋執(zhí)行淮野,修改AO對象
function check(a) {
// 此時的AO對象就是預(yù)編譯結(jié)束之后的樣子
? ? // AO {
? ? // a : function a() {},
? ? // b : undefined,
? ? // d : function d() {}
? ? // }
? ? console.log(a); //輸出function a() {}
? ? var a = 123; //預(yù)編譯已經(jīng)將var a提升執(zhí)行過了捧书,所以直接執(zhí)行賦值a=123
? ? // AO {
? ? // a : 123,
? ? // b : undefined,
? ? // d : function d() {}
? ? // }
? ? console.log(a); //輸出123
? ? function a() {} //預(yù)編譯已經(jīng)提升聲明了,被優(yōu)先執(zhí)行了骤星,所以不看了
? ? console.log(a); //輸出123
? ? var b = function () {} //預(yù)編譯已經(jīng)將變量b的聲明提升執(zhí)行了经瓷,所以只用看賦值
? ? // AO {
? ? // a : 123,
? ? // b : function() {},
? ? // d : function d() {}
? ? // }
? ? console.log(b); //輸出function() {}
? ? function d() {} //預(yù)編譯已經(jīng)提升聲明了,被優(yōu)先執(zhí)行了洞难,所以不看了
}
check(1); //函數(shù)執(zhí)行舆吮,實參為1
03 綜合例題------全局和局部的預(yù)編譯和解釋執(zhí)行過程
現(xiàn)在就通過下面的代碼來練習(xí)一下全局和局部一起的預(yù)編譯和它們的執(zhí)行過程:
console.log(test);
function test(test) {
? ? ? ? ? ? console.log(test);
? ? ? ? ? ? var test = 234;
? ? ? ? ? ? console.log(test);
function test() { }
}
test(1);
var test = 123;
1. 全局預(yù)編譯三部曲
(1)創(chuàng)建GO對象:全局預(yù)編譯的情況下,會生成Global Object對象队贱,其實和AO同理色冀,只是換了個名字。(GO === window)
GO {}
(2)找變量聲明作為GO屬性名柱嫌,值為undefined
GO {
test : undefined
}
(3)找函數(shù)聲明呐伞,值賦予函數(shù)體
GO {
test : function test(test) {...}
}
2. 局部預(yù)編譯四部曲
(此時的AO對象為函數(shù)test里的)
(1)創(chuàng)建AO對象
AO {}
(2)找形參和變量聲明賦值undefined
AO {
test : undefined
}
(3)實參形參統(tǒng)一
AO {
test: 1
}
(4)找函數(shù)聲明,值賦予函數(shù)體
AO {
test: function test() {}
}
123
3. JavaScript的解釋執(zhí)行
// js開始解釋執(zhí)行
//全局
// GO {
// test : function test(test) {...}
// }
console.log(test); // function test(test) {...}
function test(test) {
// 局部
// AO {
// test: function test() {}
// }
console.log(test); // function test(){}
var test = 234;
// AO {
// test: 234
// }
console.log(test); // 234
function test() {}//預(yù)編譯已經(jīng)提升了聲明慎式,被優(yōu)先執(zhí)行了伶氢,所以不看了
}
test(1);
var test = 123;
// GO {
// test : 123
// }
console.log(test);? //123
// js執(zhí)行結(jié)束
注意:如果GO中和AO中都有test函數(shù)趟径,若在局部中就先找AO的,但如果AO沒有的話再找GO癣防;若在全局中就找GO的用蜗巧。(就近找,自己沒有找爸爸蕾盯,爸爸沒有找爺爺?shù)龋?/p>
個人筆記幕屹,歡迎大家交流探討!
百度網(wǎng)盤鏈接:https://pan.baidu.com/s/1vF1A7beP0oovDaUFvjY9MA?提取碼:?r5d3