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