es6 import 與 export
1、export 命令
export 命令用於規定模組的對外介面。
一個模組就是一個獨立的檔案。該檔案內部所有的變數,外部無法獲取。要想外部能夠讀取模組內部的某個變數,就必須使用 export 關鍵字輸出該變數。
語法:
1 export { name1, name2, …, nameN }; 2 export { variable1 as name1, variable2 as name2, …, nameN }; 3 export let name1, name2, …, nameN; // also var 4 export let name1 = …, name2 = …, …, nameN; // also var, const 5 6 export default expression; 7 export default function (…) { … } // also class, function* 8 export default function name1(…) { … } // also class, function* 9 export { name1 as default, … }; 10 11 export * from …; 12 export { name1, name2, …, nameN } from …; 13 export { import1 as name1, import2 as name2, …, nameN } from …;
nameN ---> 匯出的識別符號(用來被其它指令碼的 import 匯入)
//aa.js export var firstName = "Muhan" export var lastName = "Wu" export var year = 2017
在 aa.js 檔案中,儲存了使用者資訊,es6 將其視為一個模組,用 export 命令對外輸出 3 個變數。我們還可以用另外一種寫法來實現
//aa.js var firstName = "Muhan" var lastName = "Wu" var year = 2017 export {firstName, lastName, year}
這種寫法在 export 命令後面使用大括號指定所要輸出的一組變數,應該被優先考慮,因為這樣就可以在指令碼尾部,一眼看清楚輸出了哪些變數
export 命令除了輸出變數,還可以輸出函式或類(Class)
在 my-module.js 模組裡,我們可以這樣匯出
// my-module.js export function cube(x) { return x*x*x } const foo = Math.PI + Math.SQRT2 export {foo}
在其它指令碼,我們可以這樣匯入:
import {cube, foo} from './my-module.js' console.log( cube(3) ) // 27 console.log( foo ) // 4.555806215962888
通常情況下,export 輸出的變數就是本來的名字,但是可以使用 as 關鍵字來重新命名
// my-module.js function aa () { console.log('My name is Kobe Bryant') } function bb () { console.log('I am one of the best players in NBA history') } export { aa as personName, bb as selfIntro, bb as selfEvaluation
上面程式碼使用 as 關鍵字,重新命名了函式 aa 和 bb 的對外介面。重新命名後,bb 可以用不同的名字輸出兩次
import {personName, selfIntro, selfEvaluation} from './my-module' personName() // My name is Kobe Bryant selfIntro() // I am one of the best players in NBA history selfEvaluation() // I am one of the best players in NBA history
注意:
(1)、export 命令規定的對外介面,必須與模組內部的變數建立一一對應的關係
// 報錯,SyntaxError export 1 // 報錯,SyntaxError var m = 1 export m /* ================================= */ // 正確寫法一 export var m = 1 // 正確寫法二 var m = 1 export {m} // 正確寫法三 var m = 1 export {m as num}
// 報錯 function myFun () { // ... } export myFun // 正確寫法一 export function myFun () { // ... } // 正確寫法二 function myFun () { // ... } export {myFun}
(2)、export 命令可以出現在模組的任何位置,只要處於模組頂層就可以。如果處於塊級作用域內,就會報錯(同樣適用於 import 命令)
function foo() { export default 'bar' // SyntaxError } foo() // Module build failed: SyntaxError: 'import' and 'export' may only appear at the top level
2、import 命令
import 用於從一個已經匯出的外部模組或另一個指令碼中匯入函式,物件或原始型別
使用 export 命令定義了模組的對外介面以後,其它 js 檔案就可以通過 import 命令載入這個模組
語法:
1 import defaultMember from "module-name"; 2 import * as name from "module-name"; 3 import { member } from "module-name"; 4 import { member as alias } from "module-name"; 5 import { member1 , member2 } from "module-name"; 6 import { member1 , member2 as alias2 , [...] } from "module-name"; 7 import defaultMember, { member [ , [...] ] } from "module-name"; 8 import defaultMember, * as name from "module-name"; 9 import "module-name";
defaultMember
將引用從模組預設匯出的名稱
module-name
要匯入的模組的名稱
name
是將引用匯出成員的名稱,指向匯入模組的物件的名稱
member,memberN
指定獨立成員,將要匯入的匯出成員的名稱
alias,aliasN
將引用命名匯入的名稱
// my-module.js var firstName = "Muhan", lastName = "Wu", year = 2017; export {firstName, lastName, year} // 引用模組 import {firstName, lastName, year} from './my-module' console.log('My name is '+firstName+lastName+ ', I am '+year+' years old!') // My name is MuhanWu, I am 2017 years old!
同 export 命令一樣,如果想為輸入的變數重新取一個名字,import 命令要使用 as 關鍵字,將輸入的變數重新命名
// my-module.js var aa = "Kobe Bryant" export {aa} --------------------------------------------------------------- import {aa as name} from './my-module' console.log('My name is '+ name) // My name is Kobe Bryant
注意:
(1)、import 命令具有提升效果,會提升到整個模組的頭部,首先執行
// my-module.js var aa = "Kobe Bryant" export {aa} ------------------------------------------------------ console.log('My name is '+ aa) // My name is Kobe Bryant import {aa } from './my-module'
上面的程式碼沒有報錯,因為 import 的執行早於 aa的呼叫
(2)、由於 import 是靜態執行,所以不能使用表示式和變數,這些只有在執行時才能得到結果的語法結構
// 報錯 import { 'f' + 'oo' } from 'my_module'; // 報錯 let module = 'my_module'; import { foo } from module; // 報錯 if (x === 1) { import { foo } from 'module1'; } else { import { foo } from 'module2'; }
(3)、如果多次重複執行同一句 import 語句,那麼只會執行一次,不會執行多次
import { foo } from 'my_module'; import { bar } from 'my_module'; // 等同於 import { foo, bar } from 'my_module';
3、export default 命令
從前面的例子可以看出,使用import命令的時候,使用者需要知道所要載入的變數名或函式名,否則無法載入。但是,使用者肯定希望快速上手,未必願意閱讀文件,去了解模組有哪些屬性和方法。
為了給使用者提供方便,讓他們不用閱讀文件就能載入模組,就要用到export default命令,為模組指定預設輸出
// my-module.js 預設輸出是一個函式 export default function () { console.log('export default') } ------------------------------------------------------------ // 其他模組載入該模組時,import命令可以為該匿名函式指定任意名字 import aaa from './my-module' aaa() // export default
上面的 import 命令,可以用任意名稱指向 my-module.js 輸出的方法,這時就不需要知道原模組輸出的函式名。需要注意的是,這時 import 命令後面,不適用大括號
export default 命令用在非匿名函式前,也是可以的
// my-module.js 預設輸出是一個函式 export default function myFun () { console.log('Hello World!') } // 或者寫成 function myFun () { console.log('Hello World!') } export default myFun ---------------------------------------------------------------- import myFun from './my-module' myFun() // Hello World!
上面程式碼中,foo函式的函式名foo,在模組外部是無效的。載入的時候,視同匿名函式載入。
下面比較一下預設輸出和正常輸出
// 第一組 export default function crc32() { // 輸出 // ... } import crc32 from 'crc32'; // 輸入 // 第二組 export function crc32() { // 輸出 // ... }; import {crc32} from 'crc32'; // 輸入
上面程式碼的兩組寫法,第一組是使用export default時,對應的import語句不需要使用大括號;第二組是不使用export default時,對應的import語句需要使用大括號
一個模組只能有一個預設輸出,所以 export default 命令只能使用一次,正因為如此,import 命令後面才可以不用加大括號。本質上,export default就是輸出一個叫做default的變數或方法,然後系統允許你為它取任意名字。所以,下面的寫法是有效的。
// modules.js function add(x, y) { return x * y; } export {add as default}; // 等同於 // export default add; // app.js import { default as xxx } from 'modules'; // 等同於 // import xxx from 'modules';
下面程式碼中,export default a的含義是將變數a的值賦給變數default。所以,最後一種寫法會報錯。
// 正確 export var a = 1; // 正確 var a = 1; export default a; // 錯誤 export default var a = 1;
同樣地,因為export default本質是將該命令後面的值,賦給default變數以後再預設,所以直接將一個值寫在export default之後
// 正確 export default 42; // 指定對外介面為 default // 報錯 export 42; // 沒有指定對外的介面
注意:import 和 export 目前無法直接在瀏覽器中實現,而是需要通過轉換器,如:Traceur Compiler、Babel、RollUp或 Webpack