幾分鐘掌握JavaScript預解析的那些坑

JavaScript預解析

1Q:未聲明變量,直接輸出會出現什麼結果?

console.log(num);

1A:報錯:變量未被定義。

Uncaught ReferenceError: num is not defined

2Q:在輸出變量後才聲明並賦值變量會出現什麼結果?1

console.log(num);
var num = 10;

2A:顯示undefined

undefined

3Q:先調用函數,再定義函數會出現什麼結果?2

fn();
function fn() {
    console.log('Javier_Ji');
}

3A:正常顯示。

Javier_Ji

4Q:先調用函數,再聲明函數表達式會出現什麼結果?3

fn();
var fn = function() {
    console.log('Javier_Ji');
}

4A:錯誤:fn不是函數。

Uncaught TypeError: fn is not a function

解釋

  1. JavaScript代碼是由瀏覽器中的JavaScript解析器來執行的。JavaScript解析器在運行JavaScript代碼的時候分爲兩步:
    • 預解析:js引擎會把js裏面的所有的var以及function提升到當前作用域的最前面。
    • 代碼執行:按照代碼書寫的順序從上往下執行。
  2. 預解析分爲:變量預解析(變量提升)和函數預解析(函數提升)
    • 變量提升:把所有的變量聲明提升到當前的作用域最前面,不提升賦值操作。
    • 函數提升:把所有的函數聲明提升到當前的作用域最前面,不調用函數。

示例

下面的代碼執行後會得到什麼結果?4

fn();
console.log(c);
console.log(b);
console.log(a);

function fn() {
    var a = b = c = 9;
    console.log(a);
    console.log(b);
    console.log(c);
}

執行後結果如下:

9
9
9
9
9
Uncaught ReferenceError: a is not defined

  1. 針對2Q的解答
    先預解析,相當於執行了如下代碼:

    var num;			//把變量聲明提升到當前作用域(本例中是全局)最前面
    console.log(num);	//執行後續的代碼
    num = 10;			//賦值
    
    ↩︎
  2. 針對3Q的解答
    先預解析,相當於執行了如下代碼:

    function() {
        console.log('Javier_Ji');
    }				//把函數聲明提升到當前作用域(本例中是全局)最前面
    fn();			//執行後續的代碼,函數被正常調用
    
    ↩︎
  3. 針對4Q的解答
    先預解析,相當於執行了如下代碼:

    var fn;			//把var聲明提升到當前作用域(本例中是全局)最前面
    fn();			//執行後續的代碼,由於函數還沒被定義,且var fn;語句定義的是變量,則會報錯,fn不是函數
    function() {
        console.log('Javier_Ji');
    }				//執行後續的代碼
    
    ↩︎
  4. 針對示例的解答
    先預解析,相當於執行了如下代碼:

    function fn() {
        var a;				
        a = b = c = 9;
        console.log(a);
        console.log(b);
        console.log(c);
    }
    fn();
    console.log(c);
    console.log(b);
    console.log(a);
    

           本例中的代碼var a = b = c = 9;相當於先在函數內部定義變量var a,之後賦值a = b = c = 9,由此可得,變量a的作用域是在fn函數內部,而bc相當於定義了一個全局變量。 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章