首先先下個結論,javascript代碼在執(zhí)行時表面并不是由上到下一行一行執(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
這時可以得到結論:變量a被聲明為了全局變量
下面回到正題:
a = 1;
var a;
console.log(a); // 1
這時候a的值為1,是為什么呢?還是因為a被聲明為全局變量了么?先來看下一個例子:
(function() {
a = 1;
var a;
console.log(a); // 1
})();
console.log(a); // ReferenceError
很奇怪,第二個console的結果a是未被定義的。現(xiàn)在回想或者到文章開頭看看一開始的結論,是不是明白了點什么。那代碼執(zhí)行真正的順序是什么樣的呢?往下看
console.log(a); // undefined
var a = 1;
a的值是undefined,說明a在console之前就已經(jīng)聲明了,但是并沒有賦值。上面代碼塊可以理解為一下代碼:
var a;
console.log(a);
a = 1;
現(xiàn)在可以有第二個結論了:
引擎會在解釋 JavaScript 代碼之前首先對其進行編譯。編譯階段中的一部分工作就是找到所有的聲明,并用合適的作用域將它們關聯(lián)起來。所以正確的思路應該是: 所有變量的聲明都會在任何代碼被執(zhí)行前首先被處理(函數(shù)也一樣)。
當我們看到var a = 1;時,javascript其實是將它看成兩個語句:var a; 和 a = 1; 聲明是在編譯階段進行的,而賦值操作等待在原地等待被執(zhí)行。這就叫提升。
注意:提升只會提升到當前作用域!