1. 程式人生 > >export 與export default區別

export 與export default區別

1、ES6之前的模組化

JavaScript最初被設計時並不是用來大型應用的,所以在其設計中也並沒有模組化標準。隨著其應用越來越廣泛,一些開源社群和開發者提出了一些模組標準,如:CommoneJS模組化、非同步模組定義(AMD)等。這些規範在提出後得到了廣泛關注,並逐步被應用到了一些企業級的大型應用。

CommoneJS模組化:該標準最成功的應用是Node.js(Node.js在CommoneJS的基礎上就進行了一定的擴充套件)。其主要特點是語法簡潔,模組使用同步載入機制,主要使用在伺服器端。

非同步模組定義(AMD):該標準的典型應該是RequireJS。其主要特點是模組使用非同步載入,主要使用在瀏覽器端。

2、ES6模組系統

它具有以下特性:

  • 簡潔的語法。語法將比CommoneJS更簡單,只使用export和import實現模組的匯出和匯入
    • 使用export關鍵字定義匯出物件,這個關鍵字可以無限次使用
    • 使用import關鍵字引入匯入物件,這個關鍵字可匯入任意數量的模組
  • 模組結構可以做靜態分析。這使得在編譯時就能確定模組的依賴關係,以及輸入和輸出的變數
  • 模組支援非同步載入
  • 為載入模組提供程式設計支援,可以按需載入
  • 比CommonJS更優秀的迴圈依賴處理

支援狀況

ES6為JavaScript帶來了模組機制,但ES6的模組機制在當前所有的瀏覽器及Node.js中均不受支援。但我們可以通過一些編譯器來對ES6語法進行轉換,從而利用這些新特性給我們專案帶來便利:

Babel-Babel是一個ES6語法轉換為ES5語法的轉換器,其支援對ES6模組語法的轉換,包括:非同步載入、狀態隔離、頂級名稱空間隔離等
-將ES6模組編譯為AMD規範或者CommonJS規範的模組
-能支援動態載入ES6風格的模組
-Google開發的JS轉換編譯器,目的在於支援更多的JavaScript特性包括ES6模組

匯出物件
在現有的模組系統中,每個JavaScript程式碼檔案在ES6中都是一個模組。只有模組中的物件需要被外部呼叫時,模組才會輸出物件,其餘則都是模組的私有物件。該處理方式將細節進行封裝,僅匯出必要的功能。

內聯匯出
ES6模組裡的物件可在建立它們的宣告中匯出。一個模組中可無數次使用export,所有的物件將被一起匯出。請看下面的例子:

export class Employee{
  constructor(id, name, dob){
    this.id = id;
    this.name=name;
    this.dob= dob;
  }
  getAge(){
    return (new Date()).getYear() - this.dob.getYear();
  }
}
export function getEmployee(id, name, dob){
  return new Employee(id, name, dob);
}
var emp = new Employee(1, "Rina", new Date(1987, 1, 22));

案例中的模組匯出了兩個物件: Employee類,getEmployee函式。因物件emp未被匯出,所以其仍為模組私有。

匯出一組物件
儘管內聯匯出很有效,但在大規模模組中,它就很難發揮作用了,因為我們可能無法追蹤到模組匯出來的物件。在這種情況下,更好的辦法是,在模組的末尾單獨進行匯出宣告,以匯出該模組中的全部物件。

class Employee{
  constructor(id, name, dob){
    this.id = id;
    this.name=name;
    this.dob= dob;
  }
  getAge(){
    return (new Date()).getYear() - this.dob.getYear();
  }
}
function getEmployee(id, name, dob){
  return new Employee(id, name, dob);
}
var x = new Employee(1, "Rina", new Date(1987, 1, 22));
export {Employee, getEmployee};

在匯出時,重新命名物件也是可以的。如下例所示,Employee在匯出時名字改為了Associate,函式GetEmployee改名為getAssociate。

export {
    Associate as Employee,
    getAssociate as getEmployee
  };

Default匯出
使用關鍵字default,可將物件標註為default物件匯出。default關鍵字在每一個模組中只能使用一次。而預設匯出每個匯出只有一個單一值,這個輸出可以是一個函式、類或其它型別的值

export default function() {}; // 可以匯出一個函式
export default class(){}; // 也可以出一個類
const D = 123;

export default D; 
export { D as default };       //與上面的等價

匯入模組

現有模組可以使用關鍵字import匯入到其它模組。一個模組可以被匯入任意數量的模組中。下文展示了匯入模組的不同方式。

如果模組包含一些邏輯要執行,且不會匯出任何物件,此類物件也可以被匯入到另一模組中。如下面案例所示:

import './module1.js';

匯入預設物件

採用Default匯出方式匯出物件,該物件在import宣告中將直接被分配給某個引用,如下例中的“d”。

import d from './module1.js';
import { default as d } from './module1.js';  //等價於上面

匯入命名的物件

正如以上討論的,一個模組可以匯出許多命名物件。如果另一模組想匯入這些命名物件,需要在匯入宣告中一一列出這些物件。舉個例子:

import {Employee, getEmployee} from './module1.js';

當然也可在同一個宣告中匯入預設物件和命名物件。這種情況下,預設物件必須定義一個別名,如下例。

 import {default as d, Employee} from './module1.js';

匯入所有物件

以上幾種情況,只有import宣告中列舉的物件才會被匯入並被使用,而其它物件則無法在匯入模組中使用。當然,這就要求使用者瞭解哪些物件可以匯出並加以利用。如果模組匯出大量物件,另一模組想引入所有匯出的物件,就必須使用如下宣告:

import * as allFromModule1 from './module1.js';

allFromModule1這一別名將指向所有從module1匯出的物件。在匯入模組中,它們作為屬性可被訪問。

可程式設計式的按需匯入

如果想基於某些條件或等某個事件發生後再載入需要的模組,可通過使用載入模組的可程式設計API(programmatic API)來實現。使用System.import方法,可按程式設定載入模組。這是一個非同步的方法,並返回Promise。

System.import('./module1.js')
    .then(function(module1){
        //use module1
    }, function(e){
        //handle error
    });