前言
js屬于解釋型語言遮婶,在執(zhí)行過程中順序執(zhí)行,但是會分塊先預(yù)編譯然后執(zhí)行猛蔽。因此在js中存在一種變量提升的現(xiàn)象剥悟。因為有了js的預(yù)編譯所以才有我們說的變量提升灵寺。
javascript 代碼運行的三大步驟
- 詞法分析:就是檢查一遍js代碼里有無語法錯誤(比如少分號,多括號等)区岗,語法分析期間不會執(zhí)行代碼略板。
- 預(yù)編譯:這個階段發(fā)生在代碼執(zhí)行的前一刻,就是在內(nèi)存里創(chuàng)建一個空間慈缔,用來存放定義的變量和函數(shù)蚯根。
- 解釋執(zhí)行:執(zhí)行代碼。
變量提升
變量提升規(guī)則
函數(shù)聲明整體提升(無論函數(shù)調(diào)用和聲明的位置是前是后胀糜,系統(tǒng)總是把函數(shù)聲明移到調(diào)用前面)
變量聲明替僧呢(無論變量調(diào)用和聲明的位置是前是后颅拦,系統(tǒng)總會把聲明移到調(diào)用前,僅僅只是聲明教藻,值仍是undefined距帅,只有在執(zhí)行階段才會進(jìn)行變量初始化。匿名函數(shù)不參與預(yù)解析括堤。)
變量提升概念
js在代碼執(zhí)行前碌秸,會將所有變量的定義提到最前面,聲明的函數(shù)也有這樣的效果悄窃。
console.log(a);
var a = 123;
// undefined
console.log(bbb);
var bbb
/// undefined
console.log(b)
function b(){
console.log('你好讥电,吃了嗎?');
}
//? b(){console.log('你好轧抗,吃了嗎恩敌?');}
變量未聲明直接使用的情況下,瀏覽器會報錯 xxx is not defined横媚。
console.log(aaa);
ReferenceError: aaa is not defined
全局變量
在瀏覽器中纠炮,在全局作用域下聲明的變量。-- 顯式聲明
var a = 123 // window.a 123
變量未經(jīng)聲明灯蝴,直接賦值的變量恢口。-- 隱式聲明
b = 123
function c(){
d = 123
}
c()
// window.b window.d 123
使用window聲明的變量。全局變量全是window的屬性穷躁。
function c(){
window.dd = 123
}
c()
// window.dd 123
預(yù)解析
概念
預(yù)解析代碼耕肩,主要會把var、function问潭、參數(shù)等一些東西存儲到內(nèi)存里猿诸。
- var一般用于聲明變量,預(yù)解析代碼的時候睦授,等號后面的賦值過程不會執(zhí)行两芳。
- function函數(shù)預(yù)解析時候摔寨,值就是函數(shù)里面的內(nèi)容去枷。
Global Object 和 Activation Object
js 在執(zhí)行前會產(chǎn)生一個GO,就是全局作用域。當(dāng)一個方法被調(diào)用時删顶,會形成一個局部作用域AO竖螃。
GO對象的預(yù)編譯過程如下:
創(chuàng)建GO對象
尋找變量聲明(var),值為undefined
-
尋找函數(shù)聲明逗余,將函數(shù)名作為GO的屬性名特咆,值為函數(shù)體
function test(){ var a = b = 123 } test() // GO:{ test:test() }
AO對象的預(yù)編譯過程如下:
- 創(chuàng)建AO對象
- 找函數(shù)的形參和變量聲明(var),作為AO屬性名录粱,值為undefined
- 形參和實參統(tǒng)一腻格,賦值
- 找函數(shù)聲明,將函數(shù)名作為AO屬性名啥繁,值為函數(shù)
function fn(){
console.log(a);
var a = 123;
console.log(a);
function a(){}
console.log(a);
var b = function(){}
console.log(b);
function d(){}
}
fn(1)
* AO:{
* a:fn
* b:undefined
* d:fn
* }
// fn 123 123 fn