本文一共 600 字,讀完只需 3 分鐘
一、概述
JS 中,我們會理所當然地認為程式碼是一句一句地執行的,但並不完全正確。
singer = "周杰倫";
var singer;
console.log(singer); // 周杰倫
sing(); // 故事的小黃花
function sing() {
console.log("故事的小黃花");
}
複製程式碼
以上第一段程式碼,如果按照正常流程,後面的 var singer
會重新把值預設宣告為 undefined
,但結果卻是 '周杰倫';
以上第二段程式碼,會理解成,先執行,後宣告,就會報錯,但結果卻沒有。
以上程式碼塊其實是可以改寫成這樣的:
var singer = undefined;
singer = "周杰倫";
console.log(singer); // 周杰倫
function sing() {
console.log("故事的小黃花");
}
sing(); // 故事的小黃花
複製程式碼
這是因為:
JS 定義宣告會在編譯階段進行,賦值和其他操作則是在執行階段進行。
所以,先有宣告,再有賦值和執行,這就是變數和函式的宣告提升。
二、函式宣告優先於變數宣告;
var foo = "bar";
function foo() {
}
typeOf(foo); // string
var foo = "bar";
function foo() {
}
typeOf(foo); // string
複製程式碼
無論函式宣告放在變數宣告前,還是後,變數宣告都覆蓋了函式宣告。
三、每個域都會進行宣告提升
以下程式碼會輸出 10,是為什麼呢?
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
複製程式碼
因為:
每個域都會進行宣告提升。
上面程式碼相當於:
var foo = 1;
function bar() {
var foo = undefined;
if (!foo) { // !foo === true
var foo = 10;
}
alert(foo);
}
bar();
複製程式碼
四、函式表示式不會宣告提升
首先,什麼是函式表示式?
// 函式宣告
function foo() {
console.log("函式宣告");
}
// 函式表示式
var foo = function() {
console.log("函式表示式");
}
複製程式碼
函式表示式,不會宣告提升,所以:
foo(); // Uncaught TypeError: foo is not a function
// 函式表示式
var foo = function() {
console.log("函式表示式");
}
複製程式碼
總結
JavaScript 中存在一種宣告提升的機制,有變數宣告和函式宣告。JS 引擎會在編譯階段查詢每個作用域的宣告,而賦值和運算則在執行時進行。
函式定義分為函式宣告和函式表示式,其中,函式宣告有宣告提升,函式表示式則沒有。
歡迎關注我的個人公眾號“謝南波”,專注分享原創文章。