抄自阮一峯ECMAScript 6 入門
export命令
模塊功能主要由兩個命令構成:export
和import
。export
用於規定模塊的對外接口,import
用於引入其餘模塊提供的方法功能。es6
一個模塊就是一個獨立的文件,該文件內部全部全部變量,外部沒法獲取。若是要從外部獲取某個變量,就必須用export
輸出該變量。函數
輸出方式
- 輸出變量申明
export var a=1; export var b=2; export var c='aaaaaaa';
- 以對象形式輸出
var a=1; var b=2; var c='aaaaaaa'; export {a, b ,c };
- 出了輸出變量還能夠輸出函數和類(class)。
export function aaa(x,y){ return x*y; } //輸出一個函數
- 通常狀況下輸出變量或者函數直接輸出器其原本的名字,方便記憶,便於整理,可是若是有特殊用途,便於區分能夠爲輸出內容自定義輸出名。
function a(){………………} function b(){………………} export { a as aPlus, b as bPlus, b as xPlus } // b 能夠用不一樣名字輸出兩次
注意事項url
export
規定的是對外的接口,必須與模塊內部變量創建一一對應的關係。spa
export 1; //報錯 var a= 1; export a ; //報錯
上面兩種寫法都會報錯,由於沒有提供對外的接口。第一種寫法直接輸出 1
,第二種寫法經過變量m
,仍是直接輸出 1
。1
只是一個值,不是接口。正確的寫法是下面這樣。.net
//正確寫法 export var a = 1; //輸出變量申明 var a = 1 ; export { a }; //以對象形式輸出 var a = 1 ; export { a as b, //重命名 a as c }
上面三種寫法都是正確的,規定了對外的接口m
。其餘腳本能夠經過這個接口,取到值1
。它們的實質是,在接口名與模塊內部變量之間,創建了一一對應的關係。3d
一樣的,function
和class
的輸出,也必須遵照這樣的寫法。code
另外,export
語句輸出的接口,與其對應的值是動態綁定關係,即經過該接口,能夠取到模塊內部實時的值。對象
export var a = 111; setTimeout(() => a = 222, 500);
上面代碼輸出變量foo
,值爲bar
,500 毫秒以後變成baz
。接口
import命令
export
命令是對外輸出接口,import命令是從外部引入接口,將別的模塊內部輸出的東西引入當前模塊使用。ip
import { a, b, c, } from './xxx.js' function test(x,y,z){ return x + y + z; } test(a,b,c);
import
命令接受一對大括號,裏面指定要從其餘模塊導入的變量名。大括號裏面的變量名,必須與被導入模塊的對外接口的名稱相同。
在引入時也能夠爲引入變量或函數從新定義命名,以下:
import { a as b} from './xxx.js' //b做爲引入變量a的新名字
經過import
引入的變量都是隻讀的,在當前模塊中可使用,但並不能更改。若是發生更改行爲則會報錯。
import { a as b} from './xxx.js' a = {};// Syntax Error : 'a' is read-only;
上面代碼中,腳本加載了變量a
,對其從新賦值就會報錯,由於a
是一個只讀的接口。可是,若是a
是一個對象,改寫a
的屬性是容許的。
import {a} from './xxx.js'; a.foo= 'hello'; //合法操做
上面代碼中,a
的屬性能夠成功改寫,而且其餘模塊也能夠讀到改寫後的值。不過,這種寫法很難查錯,建議凡是輸入的變量,都看成徹底只讀,輕易不要改變它的屬性。
import
命令有兩個部分,from
後面的部分跟的是被引入模塊文件的路徑,能夠是相對路徑也能夠是絕對路徑,若是是js文件,那麼.js
後綴能夠省略不寫。
import { a } from './xxx.js'; import { a } from './xxx';
若是隻是引入模塊名,沒有模塊路徑,則必需要有配置文件,告訴js引擎被引入模塊的位置。
import { a } from 'b';
上面代碼中的 b
是模塊名,因爲不帶有文件路徑,必須經過配置告訴js引擎怎麼找到這個模塊。
注意
import
命令具備提高效果,會提高到整個模塊的頭部首先執行。
fn(); fn2(); import {fn , fn2} from './xxx.js';
import
會提高到文件頂部首先執行,因此fn
和fn2
執行的時候,import已經被執行了,因此不會報錯。
因爲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'; }
上面三種寫法都會報錯,由於它們用到了表達式、變量和if結構。在靜態分析階段,這些語法都是無法獲得值的。
最後,import
語句會執行所加載的模塊,所以能夠有下面的寫法。
import 'lodash';
上面代碼僅僅執行lodash
模塊,可是不輸入任何值。
若是屢次重複執行同一句import
語句,那麼只會執行一次,而不會執行屢次。
import 'lodash'; import 'lodash';
上面代碼加載了兩次lodash
,可是隻會執行一次。
import { foo } from 'my_module'; import { bar } from 'my_module'; // 等同於 import { foo, bar } from 'my_module';
上面代碼中,雖然foo和bar在兩個語句中加載,可是它們對應的是同一個my_module實例。也就是說,import語句是 Singleton 模式。
模塊的總體加載
除了加載某個模塊中的某個變量或者函數以外,也能夠加載整個模塊,即用(*
)指定一個對象,將全部輸出值都加載在這個對象上面。
下面是一個circle.js
文件,它輸出兩個方法area
和circumference
。
// circle.js export function area(radius) { return Math.PI * radius * radius; } export function circumference(radius) { return 2 * Math.PI * radius; }
如今,加載這個模塊。
// main.js import { area, circumference } from './circle'; console.log('圓面積:' + area(4)); console.log('圓周長:' + circumference(14));
上面寫法是逐一指定要加載的方法,總體加載的寫法以下。
import * as circle from './circle'; console.log('圓面積:' + circle.area(4)); console.log('圓周長:' + circle.circumference(14));
注意,模塊總體加載所在的那個對象(上例是circle),應該是能夠靜態分析的,因此不容許運行時改變。下面的寫法都是不容許的。
import * as circle from './circle'; // 下面兩行都是不容許的 circle.foo = 'hello'; circle.area = function () {};
(未完)