提升
提升現象的出現,是因為程式碼在執行前,引擎會先進行編譯。這個過程就好像變數和函式宣告從它們在程式碼中出現的位置被“移動”到了最上面。
準則
- 只有宣告本身會被提升,而賦值或其他執行邏輯會留在原地。
- 每個作用域都會進行提升操作。
- 函式宣告會被提升,但是函式表示式卻不會被提升。
- 函式宣告和變數宣告都會被提升,是函式會首先被提升,然後才是變數。
- let和const進行的宣告不會再塊作用域中進行提升。
例子
示例1
console.log(a);
var a = 2;
複製程式碼
編譯後的結果是:
var a;
console.log(a); // undefined
a = 2;
複製程式碼
示例2
foo();
function foo() {
console.log(a);
var a = 2;
}
複製程式碼
編譯後的結果是:
function foo() {
var a;
console.log(a); // undefined
a = 2;
}
foo();
複製程式碼
原理參見第2條。
示例3
foo();
var foo = function() {
console.log(2);
};
複製程式碼
編譯後的結果是:
var foo;
foo(); // 不是ReferenceError,而是TypeError
foo = function() {
console.log(2);
};
複製程式碼
原理參見第三條。
示例4
foo();
var foo;
function foo() {
console.log(1);
}
foo = function() {
console.log(2);
}
複製程式碼
編譯後的結果是:
function foo() {
console.log(1);
}
foo(); // 1
foo = function() {
console.log(2);
}
複製程式碼
原理見第4條,函式被提升,然後重複宣告的變數忽略。但如果重複宣告的是函式,則發生覆蓋操作,如下:
foo(); // 3
function foo() {
console.log(1);
}
var foo = function() {
console.log(2);
};
function foo() {
console.log(3);
}
複製程式碼
編譯後的結果是:
function foo() {
console.log(3);
}
foo(); // 3
foo = function() {
console.log(2);
};
複製程式碼