ES6 module(模塊化)

前言

歷史上,JavaScript一直沒有模塊體系,沒法將一個大程序拆分紅相互依賴的小文件,再用簡單的方法拼裝起來。這對開發大型的、複雜的項目造成了巨大的障礙。react

在es6以前社區制定了一些模塊加載方案, 主要有 COmmonJS 和 AMD 兩種。前者用於服務器,後者用於瀏覽器。es6

ES6 module 和 CommonJS 及 AMD 的比較

CommonJS 和 AMD 模塊 , 採用的是 「運行時加載」 , 是將暴露的變量、方法等構成一個對象,而後再從這個而對象上讀取對應的方法。也就是說會將全部的方法都進行加載。瀏覽器

ES6模塊 ,採用的是 「編譯時加載」或者靜態加載。即只加載須要的方法,其餘的方法不加載。緩存

ES6能夠在編譯時就完成模塊加載,效率要比CommonJS高,固然,這也致使了無法引用 ES6 模塊自己,由於它不是對象。服務器

嚴格模式

ES6 的模塊自動採用嚴格模式,無論你有沒有在模塊頭部加上 "use strict"函數

嚴格模式主要有如下限制 :this

  • 變量必須聲明後再使用
  • 函數參數不能有同名屬性,不然報錯
  • 不能使用with 語句
  • 不能對只讀屬性賦值,不然報錯
  • 不能使用 arguments.callee
  • 不能使用 arguments.calles
  • 禁止this 指向全局對象
  • 不能使用前綴0表示八進制數,不然報錯
  • 不能刪除變量delete prop,會報錯,只能刪除屬性delete global[prop]
  • eval不會在它的外層做用域引入變量
  • eval和arguments不能被從新賦值
  • arguments不會自動反映函數參數的變化

export 指令

模塊功能主要有兩個命令構成 : export 和 import 。 export命令用於規定模塊的對外接口,import命令用於輸入其餘模塊提供的功能。spa

一個模塊就是一個獨立的文件。該文件內部的全部變量,外部沒法獲取。若是你但願外部可以讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量。code

  1. export 命令輸出變量 :對象

    // 1.
      export const fristName = "buzhanhua";
      //2.
      const lastName = "Jone";
      export {lastName}
    複製代碼

兩種寫法是等價的,可是推薦第二種,因爲export規定的是對外接口因此第二種要使用 {} 而不能直接名稱

  1. export 命令輸出變量或類(class)。

    export function fn(){
              console.log("zzz")
      }
      
      function fn(){
               console.log("zzz")
        }
      export {fn}
    複製代碼
  2. 一般狀況下 , export輸出的變量名稱就是之後引入時的名稱 , 可是可使用 as 關鍵字重命名。

    function fn(){
           console.log("zzz")
      }
      export {
           fn as haha,
           fn as zzzz
      }
    複製代碼

通過重命名後同一個方法能夠以不一樣的名稱屢次輸出。

  1. export語句輸出的接口,與對應的值是動態綁定的,即經過該接口,能夠取到模塊內部實時的值。

    export var foo = 'bar';
       setTimeout(() => foo = 'baz', 500);
    複製代碼

上面代碼 foo 在500 毫秒後變爲 ‘baz’ , 也就是500毫秒後再取則是baz.

這一點與CommonJS規範徹底不一樣。CommonJS模塊輸出的是值的緩存,不存在動態更新

  1. export 命令能夠出如今模塊的任何位置,只要是模塊頂層就能夠。

    function fn(){
              console.log("zzz");
              export {lastName}
      }
      // 報錯
    複製代碼

import 命令

使用export命令定義了模塊的對外接口之後,其餘 JS 文件就能夠經過import命令加載這個模塊。

  1. import命令接受一對大括號,裏面指定要從其餘模塊導入的變量名。大括號裏面的變量名,必須與被導入模塊(profile.js)對外接口的名稱相同。

    import {fristName,lastName,haha} from './profile';
    複製代碼
  2. import 命令可使用 as 關鍵字,將輸入的變量重命名。

    import {fristName as bigName} from './profile';
    複製代碼
  3. import 後面的from 指定文件的位置 , 能夠是相對路徑, 也能夠是絕對路徑,.js 能夠省略。若是隻是模塊名,不帶有路徑,那麼必須有配置文件告訴JavaScript該模塊的位置。

  4. import 命令具備提高效果,會提高到整個模塊的頭部,首先執行。

    haha();
       import {haha} from './profile';
    複製代碼

上面代碼不會報錯, 本質是由於, import命令是編譯階段執行的, 在代碼運行前。

  1. 因爲 import 是靜態執行的, 因此不能使用表達式和變量 ,這些只有在運行時才能獲得結果的語法結構。

    import {'ha'+'ha'} from './profile';
        
        let a = 'haha';
        import {a} from './profile';
        // if 語句 function 都會報錯
    複製代碼
  2. import 語句能夠執行所加載的模塊 , 但不會輸出任何值。

    import './profile';
    複製代碼
  3. 若是屢次重複執行同一句import語句,那麼只會執行一次,而不會執行屢次。

    import { foo } from 'my_module';
      import { bar } from 'my_module';
      // 等同於
      import { foo, bar } from 'my_module';
    複製代碼

上面代碼中,雖然foo和bar在兩個語句中加載,可是它們對應的是同一個my_module實例。也就是說,import語句是 Singleton 模式。

模塊的總體加載

除了指定輸出某個值,和能夠總體輸出 , 即便用 "*" 指定一個對象, 全部的輸出值都放到這個對象上。

// circle.js
     export function sum(a,b){
               console.log(a+b);
     }

     export function area(radius){
             let area = Math.PI*radius*radius;
             console.log(area);
     }

     export var a = 12;
     
     //main.js
     import * as haha from './circle';
     
      haha.sum(1,2);
      haha.area(4);
      console.log(haha.a)
複製代碼

export default 命令

使用import命令的時候,用戶須要知道所要加載的變量名或函數名,不然沒法加載。爲了給用戶提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default命令,爲模塊指定默認輸出。export default在一個模塊(文件)中只能使用一次,而export則可使用屢次。

export default function(){
               console.log("我是默認")
      }
複製代碼

其餘模塊加載該模塊時,import命令能夠爲該匿名函數指定任意名字。

import fn from './circle';
     fn() // 我是默認
複製代碼

注意 : 這時import命令後面,不使用大括號。

export default命令用在非匿名函數前,也是能夠的。

//1.
      export default function foo(){
                  console.log("我是默認")
      }
     //2.
     function foo(){
                  console.log("我是默認")
     }
     export default foo
複製代碼

上面代碼中,foo函數的函數名foo,在模塊外部是無效的。加載的時候,視同匿名函數加載。

export default輸出變量

var a = 1;
     export default a; // 正確
     
     export default 1 ; // 正確
     
     export default var a = 1 ; // 錯誤
複製代碼

由於export default命令其實只是輸出一個叫作default的變量,因此它後面不能跟變量聲明語句。上面代碼中,export default a的含義是將變量a的值賦給變量default。因此,最後一種寫法會報錯。

export default輸出類

export default class love {
          getLoverName(){
                console.log('sun')
      }
     
     }
複製代碼

若是想在一條import語句中,同時輸入默認方法和其餘變量,能夠寫成下面這樣

import react , {Component} from 'react';
複製代碼

export 與 import 的複合寫法

若是在一個模塊之中,先輸入,後輸出同一個模塊,import語句能夠與export語句寫在一塊兒

// profile.js
     export {sum,area} from './circle';
     
     //等同於
     import {sum,area} from './circle';
     export {sum,area};
     
     //main.js
     
     import {sum} from './profile';// 就可使用了
複製代碼
  1. 塊的接口更名 (as)

    export {area as pipixia} from './circle'
    複製代碼
  2. 總體輸出 (*)

    export * from './circle';
    複製代碼
  3. 獲取某個模塊的默認接口,並做爲本身的默認接口導出

    export {default} from './circle'
    複製代碼
  4. 具名接口改成本身的默認接口

    export {sum as default} from './circle';
    複製代碼
  5. 將引入的默認接口轉化爲本身的具名接口並輸出

    export {default as hei} from './circle'
    複製代碼

模塊的繼承

模塊之間也是能夠繼承的

export * from 'circle';
      export var e = 2.71828182846;
      export default function(x) {
            return Math.exp(x);
     }
複製代碼

注意,export *命令會忽略circle模塊的default方法。而後,上面代碼又輸出了自定義的e變量和默認方法。

瀏覽器的模塊加載

<script type="module" src="foo.js"></script>
複製代碼

循環加載

「循環加載」(circular dependency)指的是,a腳本的執行依賴b腳本,而b腳本的執行又依賴a腳本。

總結

1、export default

  1. export default 向外暴露成員,可使用任意變量來接收。
  2. 在一個模塊中,export default只容許使用一次。
  3. 在一個模塊中能夠同時使用export default 和 export

2、

  1. 使用export暴露的成員,只能使用{}的形式接收,這種方式叫作按需引入。
  2. export能夠向外暴露多個成員,須要哪一個用哪一個便可,不須要都用。
  3. 使用export導出的成員時,名稱必須一致。
  4. 如果非得更名則可使用as 關鍵字更名
相關文章
相關標籤/搜索