沒(méi)錯(cuò)窍箍,經(jīng)典變量提升,經(jīng)典炒冷飯丽旅,我將其稱之為典中典椰棘。
什么是提升?
引擎會(huì)在解釋 JavaScript 代碼之前首先對(duì)其進(jìn)行編譯榄笙,編譯過(guò)程中的一部分工作就是找到所有的聲明邪狞,并用合適的作用域?qū)⑺麄冴P(guān)聯(lián)起來(lái),這也正是詞法作用域的核心內(nèi)容办斑。
通俗點(diǎn)說(shuō)就是變量提升就是將變量聲明提升到它所在作用域的最頂端外恕。
在 ES6 之前,JavaScript 是沒(méi)有塊級(jí)作用域這么一說(shuō)的({}內(nèi)即為一個(gè)塊級(jí)作用域)乡翅,只有全局作用域和函數(shù)作用域鳞疲。
變量提升
全局作用域中聲明的變量會(huì)提升至全局最頂層
函數(shù)內(nèi)聲明的變量只會(huì)提升至該函數(shù)作用域最頂層
例:
var a;
console.log(a); // undefined
a = "a";
var foo = () => {
var a; // 全局變量會(huì)被局部作用域中的同名變量覆蓋
console.log(a); // undefined
a = "a1";
}
foo();
ES6 新增了 let 和 const 關(guān)鍵字,讓我們?cè)趯?xiě) JavaScript 代碼的時(shí)候更符合直覺(jué)性蠕蚜。
函數(shù)提升
函數(shù)提升和變量提升是一個(gè)道理尚洽,都是講本來(lái)應(yīng)該在后面執(zhí)行的代碼全部放到前面來(lái)。
不同之處在于 —— 變量提升是提升聲明靶累,函數(shù)提升只提升函數(shù)聲明腺毫,不會(huì)提升函數(shù)表達(dá)式。
函數(shù)提升的優(yōu)先級(jí)大于變量提升 —— 先提升函數(shù)挣柬,再提升變量
舉個(gè)栗子:
console.log(foo1);
foo1();
console.log(foo2);
foo2();
function foo1 () {
console.log("foo1");
};
var foo2 = function () {
console.log("foo2");
};
經(jīng)過(guò)預(yù)編譯后它長(zhǎng)這樣:
var foo1 = function () {
console.log("foo1");
};
var foo2;
console.log(foo1); // Function foo1(){...}
foo1(); // foo1
console.log(foo2); // undefined
foo2(); // TypeError: foo2 is not a function
foo2 = function () {
console.log("foo2");
};
看完上面的例子潮酒,有點(diǎn)同學(xué)可能還有點(diǎn)迷糊,那我們?cè)賮?lái)個(gè):
console.log(fun)
console.log(fun2)
var fun = 10
function fun(){
console.log("hello fun")
}
var fun2 = function(){
console.log("hello fun2")
}
console.log(fun)
console.log(fun2)
好邪蛔,思考一下急黎,參照上面的例子將它預(yù)編譯一遍~
// 函數(shù)提升
function fun(){
console.log("hello fun")
}
// 變量提升
var fun;
var fun2;
console.log(fun) // Function fun(){...}
console.log(fun2) // undefined
fun = 10
fun2 = function(){
console.log("hello fun2")
}
console.log(fun) // 10
console.log(fun2) // Function fun2(){...}
ES6 let const
JavaScript 中無(wú)論哪種形式聲明(var, let, const, function, function, class)都會(huì)存在提升現(xiàn)象。
不同的是 var侧到,function勃教,function 的聲明會(huì)在提升時(shí)進(jìn)行初始化賦值為 undefined,所以在訪問(wèn)這些變量的時(shí)候匠抗,不會(huì)拋出 ReferenceError 異常
而使用 let故源,const,class 聲明的變量汞贸,被提升后不會(huì)被初始化绳军,這些變量所處的狀態(tài)被被稱為“temporal dead zone”印机,此時(shí)如果訪問(wèn)這些變量會(huì)拋出 ReferenceError 異常,看上去就像沒(méi)被提升一樣删铃。