JavaScript之宣告提升

南波發表於2018-10-13

本文一共 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 引擎會在編譯階段查詢每個作用域的宣告,而賦值和運算則在執行時進行。

函式定義分為函式宣告和函式表示式,其中,函式宣告有宣告提升,函式表示式則沒有。

歡迎關注我的個人公眾號“謝南波”,專注分享原創文章。

JavaScript之宣告提升

掘金專欄 JavaScript 系列文章

  1. JavaScript之變數及作用域
  2. JavaScript之宣告提升
  3. JavaScript之執行上下文
  4. JavaScript之變數物件
  5. JavaScript原型與原型鏈
  6. JavaScript之作用域鏈
  7. JavaScript之閉包
  8. JavaScript之this
  9. JavaScript之arguments
  10. JavaScript之按值傳遞
  11. JavaScript之例題中徹底理解this
  12. JavaScript專題之模擬實現call和apply

相關文章