首頁  >  文章  >  web前端  >  es6 import會變數提升嗎

es6 import會變數提升嗎

青灯夜游
青灯夜游原創
2023-01-18 19:44:411347瀏覽

ES6 import會產生變數提升的現象。變數提升是將變數宣告提升到它所在作用域的最開始的部分。 js要經歷編譯跟執行階段,在編譯階段的時候,會蒐集所有的變量聲明並且提前聲明變量,而其他的語句都不會改變他們的順序,因此,在編譯階段的時候,第一步就已經執行了,而第二部則是在執行階段執行到該語句的時候才執行。

es6 import會變數提升嗎

本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。

變數提升

JavaScript是單執行緒語言,所以執行一定是依照順序執行。但不是逐行的分析和執行,而是一段一段地分析執行,會先進行編譯階段然後才是執行階段。在編譯階段階段,程式碼真正執行前的幾毫秒,會偵測到所有的變數和函數聲明,所有這些函數和變數聲明都被加入到名為Lexical Environment的JavaScript資料結構內的記憶體中。所以這些變數和函數能在它們真正被宣告之前使用。

先從一個簡單的例子來入手:

 a = 2;
 var a;
 console.log(a);

以上的程式碼會輸出什麼,假如這段程式碼是從上到下執行的話,肯定會輸出undefined,然而JavaScript卻不是自上而下執行的語言。 這段程式碼的輸出結果是2,意外嗎?那麼,為什麼會這樣,這個關鍵點就在於--變數提升。他會將目前作用域的所有變數的聲明,提升到程式的頂部,因此,上面的程式碼等價於以下程式碼,這樣是不是就能明白一些了?

 var a;
 a = 2;
 console.log(a);

那我們再看一個例子:

 console.log(a);
 var a = 2;

這段程式碼又會輸出什麼?輸出2嗎? 其實這段程式碼會輸出undefined。這又是為什麼呢?剛剛說過,JavaScript會將變數的宣告提升到頂部,但是賦值語句是不會提升的,對於js來說,var a = 2是分為兩步解析的:

var a;
a = 2;

而js只會提升var a 這句,所以剛剛的語句等價於:

 var a;
 console.log(a);
 a = 2;

那麼,為什麼會有變數提升?

為什麼會出現變數提升這個現象呢? 因為js與其他語言一樣,都要經歷編譯跟執行階段。而js在編譯階段的時候,會蒐集所有的變數宣告並且提前宣告變量,而其他的語句都不會改變他們的順序,因此,在編譯階段的時候,第一步就已經執行了,而第二部則是在執行階段執行到該語句的時候才執行。

ES6的import變數提升

ES6 import 會產生變數提升的現象。

例如以下的測試程式碼,

// a.js
console.log('I am a.js...')
import { foo } from './b.js';
console.log(foo);
// b.js
console.log('I am b.js...')
export let foo = 1;

運行a.js,

// node -r esm a.js 
I am b.js...
I am a.js...
1

列印的結果是先出現'I am b.js...' ,然後再出現'I am a.js...',這就是變數提升的現象。

這是因為ES6 在語言標準層面上實作了模組功能,所以當對a.js預編譯時發現關鍵字import後,先去載入b.js,所以先輸出'I am b. js...'。

整個流程是,

es6 import會變數提升嗎

變數提升的產生,其實與變數物件的建立過程有關。

變數物件創建過程

變數物件(Variable Object)的創建,依序經歷以下幾個步驟。

es6 import會變數提升嗎

  • 檢查目前上下文的函數聲明,也就是使用function關鍵字宣告的函數。在變數物件中以函數名建立一個屬性,屬性值為指向函數所在記憶體位址的參考。如果函數名的屬性已經存在,那麼該屬性將會被新的參考所覆寫。

  • 檢查目前上下文中的變數聲明,每找到一個變數聲明,就在變數物件中以變數名稱建立屬性,屬性值為undefined。如果該變數名的屬性已經存在,為了防止同名的函數被修改為undefined,則會直接跳過,原屬性值不會被修改。

function宣告會比var宣告優先權更高一點。

function test() {
  console.log(a);
  console.log(foo());

  var a = 1;
  function foo() {
    return 2;
  }
}

test();

直接從test()的執行上下文開始理解。

// 创建过程
testEC = {
    // 变量对象
    VO: {},
    // 作用域链
    scopeChain: {}
}

// VO 为 Variable Object 的缩写,即变量对象
VO = {
    arguments: {...},
    foo: <foo reference>    // 表示foo的地址引用
    a: undefined
}

test()執行的結果是,

// node -r esm demo01.js 
undefined
2

其實,上面的程式碼demo01.js,變成了這樣的執行順序,

function test() {
    function foo() {
        return 2;
    }
    var a;
    console.log(a);
    console.log(foo());
    a = 1;
}
test();

【相關推薦: javascript學習教學

以上是es6 import會變數提升嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn