ECMAScript 2015 - 模組

by vivid 22. 二月 2017 14:01

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號: N170218002
出刊日期: 2017/02/22

本文介紹ECMAScript 2015的模組(Module)語法。

什麼是模組?

在ECMAScript 5,所有定義在JavaScript檔案的程式,共享全域範圍(Global scope),為了解決變數名稱衝突與安全性的問題,ECMAScript 2015引進了模組(Module)。ECMAScript 2015只有定義模組的語法,並沒有規範要如何載入它們,讓瀏覽器或Node.js自行實作,因此目前幾乎所有瀏覽器都不支援模組的功能。

模組(Module)是一個JavaScript檔案,使用不同模式(Mode)載入。模組具備以下特性:

  • 模組(Module)自動執行在嚴格模式(Strict Mode),不能以非嚴格模式來執行。
  • 在模組上層宣告的變數,不會自動加到共享全域範圍(Shared Global scope)只存在於模組範圍。
  • 在模組上層中this的值會是「undefined」。
  • 模組中不能有HTML註解。
  • 模組的資訊必需匯出才可讓模組外部程式使用。
  • 模組可以從其它模組匯入繫結(Bindings)。

定義模組

你可以在JavaScript(*.js)檔案中,定義模組。在模組程式中,你可以使用export關鍵字,將程式顯露給其它模組,export的對象可以是變數、常數、函式(function)、類別定義…等等。

若匯出function與類別定義時,必需要有名稱,不可以匯出匿名方法(anonymous functions)或匿名類別(除非使用default關鍵字)。若沒有加export關鍵字,就代表是私有的方法,不開放外部存取。

參考以下範例程式碼,將在mymodule.js檔案中定義模組,匯出modName、id變數,PI常數,以及sayhi()方法,其中的hello()方法,就代表定義時不匯出,不過,後續還是可以搭配export關鍵字匯出,例如最後一行程式碼:

export var modName = "myModule";
export let id = 1;
export const PI = 3.14;

export function sayhi( name ) {
  return "hi , " + name;
}

export class Employee {
  constructor( id, name ) {
    this.id = id;
    this.name = name;
  }
  printInfo() {
    console.log( this.id + " , " + this.name );
  }
}


function hello( name ) {
  return "hello , " + name;
}

export {hello};

 

要注意,export關鍵字只能夠使用在最上層,不能出現在區塊陳述式之中,例如以下範例程式碼將產生錯誤:

 

if ( true ) {
  export var modName = "myModule"; //Error
}

 

匯入繫結(Binding)

在JavaScript程式中匯入模組時,以import關鍵字開始,接續大括號,代表一個繫結(Binding),以便從指定模組進行匯入,大括號之中放要匯入的識別字,像是變數或方法的名稱,from關鍵字之後則指定模組名稱。模組以字串型式表示模組所在的路徑(稱module specifier)。

import陳述式會建立唯讀的繫結(Binding),關聯到變數、函式(function)、類別(class)。參考以下範例程式碼,在mymain.js檔案中匯入mymodule模組:

import {modName} from './mymodule.js';

console.log(modName);

目前經測試,不加附檔名也可以正常運作:

import {modName} from './mymodule';

console.log(modName);

要注意,import關鍵字只能夠使用在最上層,不能出現在區塊陳述式之中,例如以下範例程式碼將產生錯誤:

if ( true ) {
  import * as mymod from './mymodule.js'; // SyntaxError
}

 

不可重複命名

若從模組匯入繫結(Binding),此繫結(Binding)視為常數值,你不可以定義一個同名的變數,例如以下範例程式碼,將產生例外錯誤:

import {modName} from './mymodule.js';

console.log(modName);

let modName = "mynew module"; // TypeError

console.log(modName);

 

匯入多個繫結(Binding)

若要一次匯入多個繫結(Binding),可以在import關鍵字後的大括號中,以逗號區隔識別字,例如以下範例程式碼,一次匯入modName、id、PI三個項目,然後印出它們的值:

import { modName, id, PI } from './mymodule.js';

console.log( modName ); // myModule

console.log( id ); // 1

console.log( PI ); // 3.14

 

匯入整個模組

你也可以匯入整個模組,將其視為一個物件,所有使用export關鍵字匯出的東西,就自動變成這個物件屬性。參考以下範例程式碼,將mymodule.js模組匯出的繫結(Bindings)載入mymod物件,接著就可以用屬性的語法來存取它們:

import * as mymod from './mymodule.js';

console.log( mymod.modName ); // myModule

console.log( mymod.id ); // 1

console.log( mymod.PI ); // 3.14

let emp1 = new mymod.Employee( 1, "Mary" );

console.log( emp1.id ); // 1

console.log( emp1.name ); // Mary

emp1.printInfo(); // 1 , Mary

let hello = mymod.hello( "candy" );

console.log( hello ); // hello , candy

這種匯入方式稱做命名空間(namespace)匯入。

 

指定匯出名稱

若模組中變數或函式(function)的名稱和自己撰寫的程式名稱衝突了,為了避免混淆,你可能不想使用模組中定義的名稱,此時在匯出時,可以指定一個新的名稱,參考以下範例程式碼,匯出sayhi()方法時,使用as關鍵字,將sayhi()方法改名為sayHello():

export function sayhi( name ) {
  return "hi , " + name;
}
export { sayhi as sayHello }

匯入繫結後就可以使用新名稱來叫用之,參考以下範例程式碼:

import * as mymod from './mymodule.js';

let hello = mymod.sayHello( "candy" );

console.log( hello ); // hi , candy

 

指定匯入名稱

除了在匯出時可以指定名稱之外,匯入繫結時,也可以指定名稱。參考以下範例程式碼,若匯出sayhi()函式如下:

export function sayhi(n ame ) {
  return "hi , " + name;
}

匯入時可以使用as關鍵字,指定新名稱:

import { sayhi as hi } from './mymodule.js';

console.log( hi("mary") ); // hi , mary

 

設定模組預設值

一個模組中只能有一個預設值(default)。你可以在變數、函式(function)或類別(class)設定為模組預設值。

參考以下範例程式碼,匯出sayhi()方法為模組的預設函式:

 

export default function sayhi(name) {
  return "hi , " + name;
}

也可以改用以下寫法,先定義要匯出的函式(function),然後使用export default關鍵字進行匯出:

function sayhi(name) {
  return "hi , " + name;
}

export default sayhi;

也可以改用以下寫法,使用export關鍵字,然後利用as default將sayhi()方法設為模組的預設函式:

function sayhi(name) {
  return "hi , " + name;
}
export {sayhi as default};

匯入模組程式如下,import關鍵字後方直接使用識別字匯入繫結,不需要使用大括號包起來:

import sayhi from './mymodule.js';

let msg = sayhi( "candy" );

console.log( msg ); //hi , candy

import關鍵字後方是一個區域變數,名稱可以自訂,例如以下範例程式碼:

import hi from './mymodule.js';

let msg = hi( "candy" );

console.log( msg ); // hi , candy

 

匯出模組預設變數

若要將匯出的變數當做模組的預設變數,可以在匯出時在變數名稱前加上default關鍵字,參考以下範例程式碼:

var modName = "myModule";

export default modName;

匯入模組時,import關鍵字後方直接使用識別字,不需要使用大括號包起來:

import n from './mymodule.js';

console.log( n ); // myModule

 

匯入一般與預設預設繫結

若模組中匯出同時匯出預設的繫結(Binding,使用default關鍵字)與一般的繫結(沒有使用default關鍵字):

export var modName = "myModule";

export default function sayhi( name ) {
  return "hi , " + name;
}

匯入繫結時,可以使用以下語法,用逗號做區格,預設繫結(Binding)的識別字不需使用大括號,一般的繫結則放在{}號之中:

import sayhi, {modName} from './mymodule.js';

console.log( modName ); // myModule

console.log(s ayhi("mary") ); // hi , mary

匯入繫結時要注意,需先匯入預設繫結,再匯入一般繫結,否則將產生例外,參考以下範例程式碼:

import {modName},sayhi from './mymodule.js'; //Error

匯入時也可以將預設繫結改名,例如將default識別字改名為「hi」,參考以下範例程式碼:

import { default as hi, modName} from './mymodule';

console.log( modName ); //myModule

console.log( hi("mary" )); //hi , mary

Tags:

.NET Magazine國際中文電子雜誌 | JavaScript | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List