了解 JavaScript 引擎在執(zhí)行代碼過(guò)程中所做的一些行為是非常必要的,這有助于我們?cè)谟龅侥涿畹恼{(diào)用時(shí),能夠大致定位問(wèn)題所在。在我學(xué)習(xí)了預(yù)編譯的相關(guān)知識(shí),并基于該文章,引用其中的一段代碼,結(jié)合“變量提升”、“函數(shù)提升”的小示例,對(duì)其進(jìn)行詳細(xì)的分析,算是留作一份筆記鞏固記憶、加深理解。
代碼
console.log(a)
fn1(1)
var a = 123
console.log(a)
var fn1 = () => {
console.log(a)
}
function fn1(a) {
console.log(a)
var a = 666
console.log(a)
function a() {}
console.log(a)
var b = function () {}
console.log(b)
function c() {}
}
fn1(1)
錯(cuò)誤的推導(dǎo)會(huì)讓你認(rèn)為上述代碼的打印如下:
如果你判斷首行報(bào)錯(cuò),那么需要了解變量提升
或者你這樣認(rèn)為
undefined
undefined
666
[Function: a]
[Function: b]
123
undefined
666
[Function: a]
[Function: b]
實(shí)際上,上方的代碼打印如下:
undefined
[Function: a]
666
666
[Function: b]
123
123
詳細(xì)分析
1. 創(chuàng)建全局對(duì)象 GO
在全局執(zhí)行上下文中,創(chuàng)建全局對(duì)象 GO
。
2. 加載當(dāng)前 JS 文件
加載并解析當(dāng)前的 JavaScript 文件。
3. 腳本語(yǔ)法分析
進(jìn)行語(yǔ)法分析,確保代碼沒(méi)有語(yǔ)法錯(cuò)誤。
4. 當(dāng)前 JS 文件預(yù)編譯
4-1. 查找變量聲明
GO = {
a: undefined
}
4-2. 查找函數(shù)聲明(除了函數(shù)表達(dá)式)
GO = {
a: undefined,
fn1: function fn1(a) {}
}
5. 正常執(zhí)行(執(zhí)行到函數(shù)調(diào)用前)
console.log(a) // 打印 undefined
fn1(1) // 執(zhí)行到這里了,小心,函數(shù)也有預(yù)編譯,執(zhí)行前一刻完成
6. 函數(shù)預(yù)編譯
6-1. 創(chuàng)建活躍對(duì)象 AO
AO = {}
6-2. 查找變量和形參
AO = {
a: undefined,
b: undefined
}
6-3. 實(shí)參值和形參統(tǒng)一
AO = {
a: 1,
b: undefined
}
6-4. 查找函數(shù)(非函數(shù)表達(dá)式)
AO = {
a: function a() {},
b: undefined,
c: function c() {}
}
7. 正常執(zhí)行函數(shù)(根據(jù) AO)
console.log(a) // 打印 function a() {}
var a = 666 // a 改變,AO.a = 666
console.log(a) // 打印 666
function a() {} // 該聲明已提升過(guò),不會(huì)覆蓋
console.log(a) // 打印 666
var b = function () {} // b 改變,AO.b = function () {}
console.log(b) // 打印 function () {}
function c() {} // 該聲明已提升過(guò),不會(huì)覆蓋
8. 接著執(zhí)行函數(shù)外代碼,執(zhí)行到下個(gè)函數(shù)調(diào)用前
fn1(1) // 已講述,上續(xù)
var a = 123 // GO 對(duì)象中的 a 改變?yōu)?123(undefined > 123)
console.log(a) // 打印 123
var fn1 = () => { // fn1 改變,GO.fn1 = () => {...}
console.log(a)
}
function fn1(a) { // 該聲明已提升過(guò)(函數(shù)提升),不會(huì)覆蓋
...
}
fn1(1) // 執(zhí)行到這里時(shí),預(yù)編譯
9. 函數(shù)預(yù)編譯
9-1. 創(chuàng)建活躍對(duì)象 AO
AO = {}
9-2. 查找變量和形參
AO = {
a: undefined
}
9-3. 實(shí)參值和形參統(tǒng)一
AO = {
a: 1
}
9-4. 查找函數(shù)(非函數(shù)表達(dá)式)
AO = {
a: 1
}
10. 正常執(zhí)行函數(shù)(根據(jù) AO)
console.log(a) // a 不存在當(dāng)前函數(shù)作用域,往上級(jí)查找,找到 GO.a,打印 123
總結(jié)
- 全局預(yù)編譯:創(chuàng)建 GO 對(duì)象,查找變量聲明和函數(shù)聲明。
- 函數(shù)預(yù)編譯:創(chuàng)建 AO 對(duì)象,查找變量和形參,實(shí)參值和形參統(tǒng)一,查找函數(shù)聲明。
- 執(zhí)行階段:按照代碼順序執(zhí)行,變量賦值和函數(shù)調(diào)用。
轉(zhuǎn)自https://www.cnblogs.com/gupingan/p/18577692