提升
之前我們講過var a = 2;後發生了什麼,它回進行兩個部分,第一部分是編譯,而第二部分是執行。故應該是聲明在前,賦值在後
a =2;
var a;
console.log(a);//2
上面三行代碼被這樣執行:
var a ;
a = 2;
console.log(a);
but ...
console.log(a);//undefined
var a = 2;
上面兩行怠慢會被這樣執行:
var a ;
console.log(a);
a = 2;
這就是變量提升
只有聲明本身會被提升,而賦值或其他運行邏輯會留在原地,接下來看下函數的提升
foo();
function foo(){
console.log(a);//undefined
var a =2 ;
}
foo可以被正常執行,因爲它函數的聲明被提升了,而且函數內部的變量提升不會超出函數範圍,相當於如下代碼:
function foo(){
var a;
console.log(a);//undefined
a = 2;
}
foo();
but...
需要謹記的一點是函數聲明可以被提升,但是函數表達式卻不會被提升。
foo();//TypeError
var foo = function bar(){
//
};
執行foo()在前,賦值在後,foo()由於對undefined值進行函數調用而導致非法錯誤,即使是具名的函數表達式,名稱標識符在賦值之前也無法在所在作用域中使用:
foo();//TypeError
bar();//ReferenceError
var foo = function bar(){
}
實際上它是這樣執行的:
var foo;
foo();
bar();
foo = function(){
var bar = ...self...
}
函數優先
函數會首先被提升,然後纔是變量。
foo();//1
var foo;
function foo(){
console.log(1);
}
foo = function(){
console.log(2);
}
實際上,是這樣的:
function foo(){
console.log(1);
}
foo();
foo = function(){
console.log(a);
}
再看:儘量避免在塊內些函數聲明。 foo();//'b'
var a = true;
if(a){
function foo(){
console.log('a');
}
}else{
function foo(){
console.log('b');
}
}