es6模塊化規則(一)

抄自阮一峯ECMAScript 6 入門

export命令

模塊功能主要由兩個命令構成:exportimportexport用於規定模塊的對外接口,import用於引入其餘模塊提供的方法功能。es6

一個模塊就是一個獨立的文件,該文件內部全部全部變量,外部沒法獲取。若是要從外部獲取某個變量,就必須用export輸出該變量。函數

輸出方式

  1. 輸出變量申明
export var  a=1;
export var  b=2;
export var  c='aaaaaaa';
  1. 以對象形式輸出
var  a=1;
 var  b=2;
 var  c='aaaaaaa';

 export  {a, b ,c };
  1. 出了輸出變量還能夠輸出函數和類(class)。
export function aaa(x,y){
    return x*y;
}
//輸出一個函數
  1. 通常狀況下輸出變量或者函數直接輸出器其原本的名字,方便記憶,便於整理,可是若是有特殊用途,便於區分能夠爲輸出內容自定義輸出名。
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,仍是直接輸出 11只是一個值,不是接口。正確的寫法是下面這樣。.net

//正確寫法

export  var a = 1;  //輸出變量申明

var  a = 1 ;
export  { a };  //以對象形式輸出

var  a = 1 ;
export  {
    a  as  b,  //重命名
    a  as  c
}

上面三種寫法都是正確的,規定了對外的接口m。其餘腳本能夠經過這個接口,取到值1。它們的實質是,在接口名與模塊內部變量之間,創建了一一對應的關係。3d

一樣的,functionclass的輸出,也必須遵照這樣的寫法。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 會提高到文件頂部首先執行,因此fnfn2執行的時候,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文件,它輸出兩個方法areacircumference

// 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 () {};

(未完)

相關文章
相關標籤/搜索