首先先下個(gè)結(jié)論,javascript代碼在執(zhí)行時(shí)表面并不是由上到下一行一行執(zhí)行的。
什么是聲明的提升?
1.眾所周知var a;如果a不賦值的話,a的值為undefined。
var a;
console.log(a); // undefined
- 未聲明直接賦值的變量
a = 1;
console.log(a); // 1
上面的代碼塊為什么打印的是1,而不是undefined呢?很明顯a是聲明了的,但是a聲明在全局作用域了還是局部作用域了呢?
- 在局部作用域給未聲明的變量賦值
(function() {
a = 1;
})()
console,log(a); // 1
這時(shí)可以得到結(jié)論:變量a被聲明為了全局變量
下面回到正題:
a = 1;
var a;
console.log(a); // 1
這時(shí)候a的值為1,是為什么呢?還是因?yàn)閍被聲明為全局變量了么?先來(lái)看下一個(gè)例子:
(function() {
a = 1;
var a;
console.log(a); // 1
})();
console.log(a); // ReferenceError
很奇怪,第二個(gè)console的結(jié)果a是未被定義的。現(xiàn)在回想或者到文章開(kāi)頭看看一開(kāi)始的結(jié)論,是不是明白了點(diǎn)什么。那代碼執(zhí)行真正的順序是什么樣的呢?往下看
console.log(a); // undefined
var a = 1;
a的值是undefined,說(shuō)明a在console之前就已經(jīng)聲明了,但是并沒(méi)有賦值。上面代碼塊可以理解為一下代碼:
var a;
console.log(a);
a = 1;
現(xiàn)在可以有第二個(gè)結(jié)論了:
引擎會(huì)在解釋 JavaScript 代碼之前首先對(duì)其進(jìn)行編譯。編譯階段中的一部分工作就是找到所有的聲明,并用合適的作用域?qū)⑺鼈冴P(guān)聯(lián)起來(lái)。所以正確的思路應(yīng)該是: 所有變量的聲明都會(huì)在任何代碼被執(zhí)行前首先被處理(函數(shù)也一樣)。
當(dāng)我們看到var a = 1;時(shí),javascript其實(shí)是將它看成兩個(gè)語(yǔ)句:var a; 和 a = 1; 聲明是在編譯階段進(jìn)行的,而賦值操作等待在原地等待被執(zhí)行。這就叫提升。
注意:提升只會(huì)提升到當(dāng)前作用域!