JS 運(yùn)行三部曲
語法分析
語法分析很簡(jiǎn)單南片,就是引擎檢查你的代碼有沒有什么低級(jí)的語法錯(cuò)誤
預(yù)編譯
預(yù)編譯發(fā)生在代碼執(zhí)行的前一刻,預(yù)編譯簡(jiǎn)單理解就是在內(nèi)存中開辟一些空間,存放一些變量與函數(shù) 愁铺;
解析執(zhí)行
解釋執(zhí)行顧名思義便是執(zhí)行代碼了
預(yù)編譯前奏
暗示全局變量 imply global
任何變量,如果變量未經(jīng)申明就賦值,此變量就為 全局對(duì)象 所有。
a = 1;
console.log(window.a);
function test() {
var a = b = 2;
}
test();
console.log(window.b);
全局變量
一切申明的 全局變量, 全是 window 的屬性, window 就是全局的域
GO 和 AO
JS 在執(zhí)行前會(huì)產(chǎn)生一個(gè) GO ,也就是我們說的全局作用域 。 當(dāng)一個(gè)方法被調(diào)用時(shí)會(huì)形成一個(gè)局部作用域 AO
全局代碼在執(zhí)行的時(shí)候,先是 變量提升 , 在全局作用域內(nèi)添加 屬性,然后是 函數(shù)(以函數(shù)聲明創(chuàng)建的函數(shù))提升,再是代碼執(zhí)行
我們先來個(gè)簡(jiǎn)單的小栗子來看看
var b = 2;
console.log(b);
console.log(b);
var b = 2;
此時(shí)我們打印出來 b 的值為 undefined,那我們不定義 b 直接 打印 b 是什么情況呢
console.log(b);
結(jié)果如上圖 瀏覽器報(bào)錯(cuò).
為什么在 console.log 前育韩,后和不定義 b 會(huì)有如此大的差別,這就是預(yù)編譯起到的作用
我們?cè)倏纯聪旅孢@個(gè)列子
console.log(a);
var a = 123;
function a() {
}
console.log(a);
結(jié)果怎么來的呢???
那我們就得看下面的 預(yù)編譯 四部曲
預(yù)編譯四部曲
創(chuàng)建 GO/AO 對(duì)象
找形參和變量申明,將變量和形參名作為 AO 屬性名,值為 undefined
將實(shí)參值和形參值統(tǒng)一
在函數(shù)體里面找函數(shù)申明,值賦予 函數(shù)體
這四部是什么意思呢,我們舉個(gè)例子看看:
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a() { }
console.log(a);
console.log(b);
var b = function () { }
console.log(b);
}
fn(1);
大家覺得應(yīng)該輸出什么呢?
我們來分析下:
首先方法調(diào)用形成一個(gè)局部 *AO
AO{
}
找方法里面的形參和變量申明, fn 里面 只有 a 和 b,作為 AO 的屬性并把值設(shè)置為 undefined
AO{
a:undefined,
b:undefined
}
然后將形參和實(shí)參的值統(tǒng)一,什么意思呢,就是給 形參 a 賦值為 實(shí)參 1,此時(shí)的 AO:
AO{
a:1,
b:undefined
}
最后一步函數(shù)體找函數(shù)申明,并賦值為函數(shù)體, 我們找到了 函數(shù)申明 function a() { } ,有人會(huì)問 b呢,不好意思 b 是 函數(shù)表達(dá)式,因此忽略,此時(shí) AO 為:
AO{
a:function a() { },
b:undefined
}
到此 函數(shù)預(yù)編譯完成,下面開始執(zhí)行:
第一次 console.log(a) 打印即為 AO 里面的 a => function a() { }
第二次 console.log(a) 執(zhí)行 a 的賦值,此時(shí) a =>123
第三次 console.log(a) 函數(shù)function a() { } 已經(jīng)預(yù)編譯申明過, 因此直接忽略, a 還是為 123
第一次 console.log(b) 打印即為 AO 里面的 b => undefined
第二次 console.log(b) 執(zhí)行 b 的賦值,此時(shí) b =>function () { }
我們來看看打印的是否如我們分析的這樣:
看來沒有問題筑舅。
好了,我們已經(jīng)知道了 預(yù)編譯的過程,那讓我們?cè)賮硪活}看看:
function test() {
console.log(b);
if (a) {
var b = 100;
}
c = 234;
console.log(b);
console.log(c);
}
var a;
test();
a = 10;
console.log(a);
console.log(c);
一樣的,我們首先生成 GO,AO
GO{
a:undefined
}
AO{
b:undefined
}
第一次打印 b 的值 為 undefined 沒問題,
此時(shí) AO 中沒有a 屬性,往上找全局屬性 GO ,ok a 為 undefined,條件不成立 b 還是 undefined
打印 c 沒什么好說的,直接就是 234
函數(shù) test() 執(zhí)行完畢 下面 a 進(jìn)行復(fù)制, 因此 打印 a 為 10
打印 c 相當(dāng)于 訪問 window.c 因此還是 234
小練習(xí)
a = 100;
function deme(e) {
function a() { }
arguments[0] = 2;
console.log(e);
if (a) {
var b = 123;
var c = function () { }
}
var c;
a = 10;
var a;
console.log(b);
f = 123;
console.log(c);
console.log(a);
}
var a;
deme(1);
console.log(a);
console.log(f);
總結(jié)
未經(jīng)申明就賦值,此變量就是全局變量所有,一切申明的全局變量,全是 window 屬性
預(yù)編譯發(fā)生在 變量申明 和 函數(shù)申明, 匿名函數(shù) 和 函數(shù)表達(dá)式 不參與預(yù)編譯
變量 聲明提升—無論變量調(diào)用和聲明的位置是前是后,系統(tǒng)總會(huì)把聲明移到調(diào)用前,注意僅僅只是聲明座慰,所以值是 undefined
函數(shù)聲明整體提升-無論函數(shù)調(diào)用和聲明的位置是前是后陨舱,系統(tǒng)總會(huì)把函數(shù)聲明移到調(diào)用前面.如果函數(shù)名同形參或變量名同名,則會(huì)賦值為 函數(shù)體
只有在解析執(zhí)行才會(huì)對(duì)變量初始化
覺得不錯(cuò)請(qǐng)幫忙點(diǎn)個(gè)贊,謝謝!!!