ES6的模塊化語法

在模塊化被寫入 ECMAScript 標準以前, 已經存在各類模塊化的實現方式和對應的語法, 例如 AMD, CMD, commonJS 等. 本文只討論 ES6 標準下的模塊化語法.模塊化

模塊化的必要性

當咱們但願全局做用域更加乾淨,而不是處處都有命名衝突之類的問題;函數

當咱們但願一段代碼擁有本身的做用域, 並且不要被其餘代碼所污染;ui

當咱們但願本身的程序更加井井有理;this

當......spa

這也是 ES6 但願解決的問題, 因此將模塊化定爲了標準.code

模塊的概念

模塊是一段JavaScript代碼, 這段代碼會自動運行、並且是在嚴格模式下、而且沒法退出運行。對象

模塊的特色

  • 模塊內定義的變量不會被自動添加到全局做用域
  • 因爲上面的緣由, 模塊要向外面暴露一些本身的數據, 這些數據能夠被外界訪問到
  • 一個模塊能夠從另一個模塊中導入數據(便可以使用其餘模塊的數據)
  • 模塊頂層的 thisundefined, 並非 windowglobal

模塊和腳本的區別

模塊和腳本初看起來很類似, 他們均可以存在一個單獨的文件中, 均可以被其餘模塊(腳本)引入, 也能夠引入其餘模塊(腳本)的數據, 彷佛很難說出他們之間的區別.ip

可是其實他們的區別很是明顯, 用一句話就能夠歸納: 咱們能夠按需導入模塊中的數據, 可是不能按需導入腳本中的數據。作用域

對於腳本,咱們一旦導入了它, 就會將腳本中的全部數據全都導入到了全局做用域中, 這樣看起來仍是挺亂的。string

而對於模塊, 則能夠只導入咱們須要的數據。雖然一個模塊可能會暴露出不少的變量、函數和對象, 但咱們能夠只把須要的那一部分導入進來使用。

從其餘模塊導入數據和將模塊中的數據暴露出去給其餘模塊的語法 exportimport

將模塊中的數據暴露(導出)給其餘模塊 export

將模塊中的數據暴露給其餘模塊使用的語法有兩種, 分別以下:

  1. 先定義一個值,而後將其暴露出去
// 定義一個變量
let name = 'doug';
// 暴露這個變量
export name;

// 定義一個函數
function say(){
    console.log('hello ' + name);
}
// 暴露這個函數
export say;

// 定義一個類
class Student {
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
}
// 暴露這個類
export Student;

// 定義一個函數,並且不把它暴露出去
function privateFunc(){
    console.log('我是私有成員,沒有被暴露出去,因此別人沒有辦法訪問到我');
}
複製代碼

上面的操做能夠分爲兩個過程, 先定義、再暴露。其實能夠簡化爲一句代碼: 2. 在定義變量的同時暴露數據, 只要在聲明符以前加上 export 就能夠.

// 定義一個變量並暴露
export let name = 'doug';

// 定義一個函數並暴露
export function say(){
    console.log('hello ' + name);
}

// 定義一個類並暴露
export class Student {
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
}

// 定義一個函數,並不把它暴露出去, 其餘模塊從外部沒法訪問這個函數
function privateFunc(){
    console.log('我是私有成員,沒有被暴露出去,因此別人沒有辦法訪問到我');
}
複製代碼

注意, 不暴露出去的數據是從外部訪問不到的, 例如上面例子中的 privateFunc 函數.

從別的模塊導入數據 import

從別的模塊獲得數據以供本身使用, 要用 import 關鍵字。在導入以前, 要先明確兩個問題: 一是從哪一個模塊導入? 二是想導入模塊中的什麼數據?

在明確從哪導入和導入什麼以後,就能夠按照下面的語法來寫了:

import { 數據1, 數據2, ... , 數據n } from 模塊名
複製代碼

例如,從 a 模塊中導入 name 變量 和 say 函數:

import { name, say } from './a.js';
複製代碼

這樣就把 name 和 say 從 a 模塊導入進本模塊中了,如今就可使用它們了, 例如輸出 name 的值, 或者調用 say 這個函數:

console.log(name);

say();
複製代碼

關於導入的注意事項

導入的數據是沒有辦法直接改變的。好比,咱們沒法直接給 name 從新賦值, 這樣會報錯。

import { name } from './a.js';

name = 'new name';  // Error 錯誤
複製代碼

可是能夠間接的修改這個變量的值. 假如在模塊 a 中定義了一個能夠修改 name 值的函數, 則能夠經過調用這個函數來修改 name 的值了. a 模塊中的內容:

... 包括 name 在內的其餘數據

function updateName(newName){
    name = newName;
}
複製代碼

導入 a模塊的 updateName 函數來修改 name 的值:

import { name, updateName } from './a.js';

updateName('new Name'); // name的值已經被修改成了 "new name"
複製代碼

一次性導入一個模塊暴露出來的全部數據

當想用一行代碼導入一個模塊暴露出來的全部數據時, 用上面的方法可能比較困難, 由於一個模塊暴露出來的方法可能不少, 把每一個變量名都寫出來的方法就不夠靈活了.

這個時候能夠用命名空間導入的方法, 即將一個模塊暴露出來的全部的數據掛載到一個對象上,經過這個對象來調用這些數據, 例如:

import * as aObj from './a.js'; // a 模塊全部暴露出的數據都掛到了 aObj 上

// 經過 aObj 來訪問和調用 a 模塊中的變量和方法
console.log(aObj.name);
aObj.say();
複製代碼

使用 as 對導入和要暴露出去的數據重命名

若是想將數據以別的名稱暴露出去, 可使用 as 關鍵字, 語法爲: export { 原名稱 as 新名稱 } .

這樣在其餘模塊中就能夠用這個新的名稱來導入這個數據了, 例如將函數 say 以 speak 爲名稱暴露出去:

export {say as speak};
複製代碼

那麼其餘模塊就要用 speak 來導入這個函數了: import { speak } from './a.js'

在導入一個數據時, 也能夠對它重命名, 並使用重命名以後的名稱來訪問它, 例如將它命名爲 Howling, 以後就可使用 howling 來訪問這個函數了:

import { speak as howling} from './a.js';  // 導入時重命名

howling(); // 用新名字調用這個函數
複製代碼

將一個值做爲默認值暴露出去 default

每一個模塊能夠將一個變量、函數或者類做爲默認值暴露出去.

將一個值做爲默認值暴露出去的語法有3種,分別是:

  1. 定義的時候就暴露
  2. 先定義後暴露
  3. 將這個值用 as 命名爲 default 後暴露
// 1. 定義的時候就暴露
export default function(){
    console.log('方法1暴露函數爲默認值');
}

// 2. 先定義後暴露
let name = 'doug';
export default name;

// 3. 將這個值用 as 命名爲 default 暴露
class Student{ // ... }
export {Student as default};
複製代碼

導入其餘模塊暴露出的默認值

導入默認值的語法和導入非默認值的語法略有不一樣. 導入一個模塊暴露出的默認值, 並不用 {} 來包裹, 並且不用使用 as 關鍵字就能夠將這個默認值重命名: 例如導入上面例子中的 name, 並將其重命名爲 familyName

import familyName from './a.js';
複製代碼

同時導入默認值和非默認值的語法

在一行語句中同時導入默認值和非默認值的語法很是簡單, 就是將這兩種導入的方式結合起來, 非默認值用{}括起來, 而默認值不用. 語法爲:

import 默認值 { 非默認值 } from './a.js';
複製代碼

將從其餘模塊導入的數據暴露出去

有時候須要將從其餘模塊導入的某些數據再暴露出去, 這有兩種語法

  1. 先導入, 再暴露
import { name } from './a.js';   // 導入

export {name};   // 暴露
複製代碼
  1. 一行代碼以內同時導入和暴露
export { name } from './a.js';
複製代碼

也能夠重命名後再暴露出去

export { name as lastName } from './a.js';
複製代碼

#完. 文章或有疏漏之處, 歡迎指正.

在模塊化被寫入 ECMAScript 標準以前, 已經存在各類模塊化的實現方式和對應的語法, 例如 AMD, CMD, commonJS 等. 後面的文章會對這些標準進行對比.

相關文章
相關標籤/搜索