ES6之模塊入門(一)

    ES6以前,一個Web應用的每一個JS文件所定義的全部內容都由全局做用域共享。當Web應用變得愈來愈複雜,須要更多的JS代碼時,此種方式會致使命名衝突、安全等不少問題。javascript

    如何解決?html

    ES6的設計目標之一就是要解決做用域問題,並讓JS應用變得更有調理。 這即是模塊的切入點。java

 

  1. 什麼是模塊(What are Modules)?

    Modules are JavaScript files that are loaded in a different mode (as opposed to scripts, which are loaded in the original way JavaScript worked).

    模塊( Modules )是使用不一樣方式加載的 JS 文件(與 JS 原先的腳本加載方式相對)es6

    簡單來講,能夠認爲一個模塊就是一個js文件,該模塊中有變量、函數、類。

    →模塊(Modules)與腳本(Script)的語義有很大的不一樣:

      一、模塊代碼自動運行在嚴格模式下,而且沒有任何辦法跳出嚴格模式;

      二、在模塊的頂級做用域建立的變量,不會自動添加到共享的全局做用域,它們只會在模塊頂級做用域的內部存在

           三、模塊頂級做用域的this值爲undefined

           四、模塊不容許在代碼中使用HTML風格的註釋;

           五、對於須要讓模塊外部訪問的內容,模塊必須導出它們;

           六、容許模塊從其餘模塊導入綁定;

    web

    咱們這裏定義一個模塊文件(calc.js)放到modules目錄下,內容以下:
    function add(a, b) {
        return a + b;
    }
    
    function sub(a, b) {
        return a - b;
    }
    
    function multi(a, b) {
        return a * b;
    }
    
    function divide(a, b) {
        return a / b;
    }
    //先定義,後導出
    export { add, sub, multi, divide }

     

  2. 如何加載模塊?
    ES6規範中定義了模塊的語法以及抽象的加載機制,但沒有定義如何加載他們,所以具體的實現環境(例如web瀏覽器、Node.js)能夠自行決定用什麼方式實現,以便契合各自的環境。

    →在Web瀏覽器中使用模塊(使用script標籤)

    方式一:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!--告訴瀏覽器 要將內聯代碼當作模塊,這是一個直接嵌入到網頁內的模塊-->
        <script type="module">
            import { add, sub, multi, divide } from './modules/calc.js';
    
            let result = add(10, 20);
            console.log('result=' + result);
        </script>
    </head>
    <body>
    </body>
    </html>

    在這裏,result變量沒有暴露到全局,由於它只在<script>元素定義的這個模塊內部存在,所以也沒有被添加爲window對象的屬性。瀏覽器

    輸出結果爲:
    安全


    方式二:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!--告訴瀏覽器 要將指定文件中的代碼當作模塊,而不是當作腳本,這裏使用src加載了外部模塊文件-->
        <script type="module" src="./modules/calc.js"></script>
    </head>
    <body>
        
    </body>
    </html>

     



  3. 模塊加載次序

    模塊相對腳本的獨特之處在於:它們能使用 import 來指定必需要加載的其餘文件,以保證正確執行。爲了支持此功能, <script type="module"> 老是表現得像是已經應用了 defer 屬性。ide

    defer 屬性是加載腳本文件時的可選項,但在加載模塊文件時老是自動應用的。當 HTML 解析到擁有 src 屬性的 <script type="module"> 標籤時,就會當即開始下載模塊文件,但並不會執行它,直到整個網頁文檔所有解析完爲止。
    模塊也會按照它們在 HTML 文件中出現的順序依次執行,這意味着第一個 <script type="module"> 老是保證在第二個以前執行,即便其中有些模塊不是用 src 指定而是包含了內聯腳本。函數

    例如:
    第一步:新建一個模塊foo.js在modules目錄下,foo.js內容以下:測試

    function hello(){
        console.log('foo.hello...');
    }
    
    console.log('foo.js模塊執行了');

    第二步:新建測試網頁foo.html,內容以下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!--外部文件方式加載模塊-->
        <!--first執行-->
        <script type="module" src="./modules/foo.js"></script>
        <!--second執行-->
        <script type="module">
            console.log('second模塊執行了...');
        </script>
        
    </head>
    <body>
        <h1>Foo</h1>
        <script type="text/javascript">
            //模擬加載數據耗時2秒
            setTimeout(() => {
                console.log('網頁模擬加載數據執行了...');
            }, 2000);
        </script>
    
        <!--third執行-->
        <script type="module">
            console.log('third模塊執行了...');
        </script>
    </body>
    </html>

    觀察執行結果:

     

     

     

  4. 總結

    ES6 爲 JS 語言添加了模塊,做爲打包與封裝功能的方式。

    模塊的行爲異於腳本,它們不會用自身頂級做用域的變量、函數或類去修改全局做用域,而模塊的 this 值爲 undefined 。爲了實現這些行爲,模塊在被加載時使用了一種不一樣的方式。

    你必須將模塊中須要向外提供的任何功能都導出,變量、函數與類均可以,而且每一個模塊容許存在一個默認導出。
    在導出以後,另外一個模塊就能導入該模塊所導出的一個或多個名稱了。這些導入的名稱就像是被 let 所定義的,會被看成塊級綁定,而且不允在同一模塊內重複聲明。


    因爲模塊必須用與腳本不一樣的方式運行,瀏覽器就引入了 <script type="module"> ,以表示資源文件或內聯代碼須要做爲模塊來執行。


    使用 <script type="module"> 加載的模塊文件會默認應用 defer 屬性。一旦包含模塊的頁面文檔徹底被解析,模塊就會按照它們在文檔中的出現順序依次執行。

 

 

參考資料:《Understanding ECMAScript 6》,做者:Nicholas C. Zakas ,在線閱讀地址:https://leanpub.com/understandinges6/read#leanpub-auto-what-are-modules

相關文章
相關標籤/搜索