最近,在讀《你不知道的JavaScript(上卷)》這本書,書中詳細闡述了JavaScript眾多重要但經常被大家忽略的點,在此強烈推薦!!!書中,第4章講述了“提升”,從示例出發講述了變量和函數提升的過程,糾正了自己以前錯誤的理解(相信好多人理解都是錯誤)!
我們習慣將var a = 2;看做一個聲明,而實際上JavaScript引擎不這么認為!下面幾個示例讓你徹底搞懂JavaScript中的變量提升!
示例1:
~~~
a = 2;
var a ;
console.log(a); //2
~~~
示例2:
~~~
console.log(b); //undefined
var b = 2;
~~~
示例3:
~~~
var c;
console.log(c); //undefined
c = 2;
~~~
示例4:
~~~
foo();
function foo(){
console.log(d); //undefined
var d = 2;
}
~~~
示例5:
~~~
bar(); //TypeError
var bar = function too(){
// ....
}
~~~
示例6:
~~~
aoo(); //TypeError
boo(); //ReferenceError
var aoo = function boo(){
// ...
}
~~~
示例7:
~~~
function foo(){
console.log(1);
}
foo(); //1
foo = function(){
console.log(2);
};
~~~
示例8:
~~~
foo(); //3
function foo(){
console.log(1);
}
var foo = function(){
console.log(2);
};
function foo(){
console.log(3);
}
~~~
示例9:
~~~
foo(); //b
var a = true;
if(a){
function foo(){ console.log("a"); }
}else{
function foo(){ console.log("b"); }
}
~~~
**總結:**
1. var a = 2;其中var a在編譯階段,a=2在執行階段;
2. 無論作用域中的聲明(變量和函數)出現在什么地方,都將在代碼本身執行前首先進行處理;
3. 聲明本身會被提升,而包括函數表達式的賦值在內的賦值操作并不會提升;
4. 函數會首先被提升,然后才是變量,重復的var(變量)聲明會被忽略掉;
5. 后面的函數聲明可以覆蓋前面的。
**PS:**
1. RHS查詢在所有嵌套的作用域中遍尋不到所需遍歷會拋出ReferenceError。
2. RHS查詢到一個變量,但你嘗試對其不合理的操作(引用null或undefined類型中的屬性),會拋出TypeError。