1. 程式人生 > >import命令與export命令

import命令與export命令

import命令

使用export命令定義了模組的對外介面以後,其他JS檔案就可以通過import命令載入這個模組(檔案)。

// main.js

import {firstName, lastName, year} from './profile';

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}

上面程式碼的import命令,就用於載入profile.js檔案,並從中輸入變數。import命令接受一個物件(用大括號表示),裡面指定要從其他模組匯入的變數名。大括號裡面的變數名,必須與被匯入模組(profile.js

)對外介面的名稱相同。

如果想為輸入的變數重新取一個名字,import命令要使用as關鍵字,將輸入的變數重新命名。

import { lastName as surname } from './profile';

注意,import命令具有提升效果,會提升到整個模組的頭部,首先執行。

foo();

import { foo } from 'my_module';

上面的程式碼不會報錯,因為import的執行早於foo的呼叫。

如果在一個模組之中,先輸入後輸出同一個模組,import語句可以與export語句寫在一起。

export { es6 as default } from './someModule'
; // 等同於 import { es6 } from './someModule'; export default es6;

上面程式碼中,exportimport語句可以結合在一起,寫成一行。但是從可讀性考慮,不建議採用這種寫法,而應該採用標準寫法。

另外,ES7有一個提案,簡化先輸入後輸出的寫法,拿掉輸出時的大括號。

// 提案的寫法
export v from 'mod';

// 現行的寫法
export {v} from 'mod';

import語句會執行所載入的模組,因此可以有下面的寫法。

import 'lodash';

上面程式碼僅僅執行lodash模組,但是不輸入任何值。

export

模組功能主要由兩個命令構成:exportimportexport命令用於規定模組的對外介面,import命令用於輸入其他模組提供的功能。

一個模組就是一個獨立的檔案。該檔案內部的所有變數,外部無法獲取。如果你希望外部能夠讀取模組內部的某個變數,就必須使用export關鍵字輸出該變數。下面是一個JS檔案,裡面使用export命令輸出變數。

// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;

上面程式碼是profile.js檔案,儲存了使用者資訊。ES6將其視為一個模組,裡面用export命令對外部輸出了三個變數。

export的寫法,除了像上面這樣,還有另外一種。

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year};

上面程式碼在export命令後面,使用大括號指定所要輸出的一組變數。它與前一種寫法(直接放置在var語句前)是等價的,但是應該優先考慮使用這種寫法。因為這樣就可以在指令碼尾部,一眼看清楚輸出了哪些變數。

export命令除了輸出變數,還可以輸出函式或類(class)。

export function multiply(x, y) {
  return x * y;
};

上面程式碼對外輸出一個函式multiply

通常情況下,export輸出的變數就是本來的名字,但是可以使用as關鍵字重新命名。

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};

上面程式碼使用as關鍵字,重新命名了函式v1v2的對外介面。重新命名後,v2可以用不同的名字輸出兩次。

需要特別注意的是,export命令規定的是對外的介面,必須與模組內部的變數建立一一對應關係。

// 報錯
export 1;

// 報錯
var m = 1;
export m;

上面兩種寫法都會報錯,因為沒有提供對外的介面。第一種寫法直接輸出1,第二種寫法通過變數m,還是直接輸出1。1只是一個值,不是介面。正確的寫法是下面這樣。

// 寫法一
export var m = 1;

// 寫法二
var m = 1;
export {m};

// 寫法三
var n = 1;
export {n as m};

上面三種寫法都是正確的,規定了對外的介面m。其他指令碼可以通過這個介面,取到值1。它們的實質是,在介面名與模組內部變數之間,建立了一一對應的關係。

同樣的,functionclass的輸出,也必須遵守這樣的寫法。

// 報錯
function f() {}
export f;

// 正確
export function f() {};

// 正確
function f() {}
export {f};

另外,export語句輸出的介面,與其對應的值是動態繫結關係,即通過該介面,可以取到模組內部實時的值。

export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

上面程式碼輸出變數foo,值為bar,500毫秒之後變成baz

這一點與CommonJS規範完全不同。CommonJS模組輸出的是值的快取,不存在動態更新,詳見下文《ES6模組載入的實質》一節。

最後,export命令可以出現在模組的任何位置,只要處於模組頂層就可以。如果處於塊級作用域內,就會報錯,下一節的import命令也是如此。這是因為處於條件程式碼塊之中,就沒法做靜態優化了,違背了ES6模組的設計初衷。

function foo() {
  export default 'bar' // SyntaxError
}
foo()

上面程式碼中,export語句放在函式之中,結果報錯。


參考資料,阮一峰http://es6.ruanyifeng.com/#docs/module#import%E5%91%BD%E4%BB%A4