JavaScript 用「共享一切」的方法加載代碼,這是該語言中最容易出錯且最容易讓人感到困惑的地方。其餘語言使用諸如包這樣的概念來定義代碼做用域,但在 ECMAScript 6 之前,在應用程序的每個 JavaScript 中定義的一切都共享一個全局做用域。隨着 Web 應用程序變得更加複雜,JavaScript 代碼的使用量也開始增加,這樣會引發問題,如命名衝突和安全問題。ECMAScript 6 的一個目標就是解決做用域問題,也爲了使 JavaScript 應用程序顯得有序,因而引進了模塊。瀏覽器
模塊是自動運行在嚴格模式下而且沒有辦法退出運行的 JavaScript 代碼。與共享一切架構相反的是,在模塊頂部建立的變量不會不會被自動添加到全局共享做用域,這個變量僅在模塊的頂級做用域中存在,並且模塊必須導出一些外部代碼能夠訪問的元素,如變量或函數。模塊也能夠從其餘模塊導入綁定。安全
另外兩個模塊的特性與做用域關係不大,但也很重要。首先,在模塊的頂部, this
的值是 undefined
;其次,模塊不支持 HTML 風格的代碼註釋,這是從早期瀏覽器殘留下來的 JavaScript 特性。架構
腳本,也就是任何不是模塊的 JavaScript 代碼,則缺乏這些特性。模塊和其餘 JavaScript 代碼之間的差別可能乍一看不起眼,可是它們表明了 JavaScript 代碼加載和求值的一個重要變化。模塊真正的魔力所在是僅導出和導入你須要的綁定,而不是將全部東西都到一個文件。只有很好地理解了導出和導入才能理解模塊與腳本的區別。ide
能夠用 export
關鍵字將一部分已發佈的代碼暴露給其餘模塊,在最簡單的用例中,能夠將 export
放在任何變量、函數或類聲明的前面,以將它們從模塊導出,像這樣:函數
//導出數據
export var color = "red";
export let name = "Nicholas";
export const magicNumber = 7;
//導出函數
export function sum(num1,num2){
return num1 + num2;
}
//導出類
export class Rectangle {
constructor(length,width){
this.length = length;
this.width = width;
}
}
//這個函數是模塊私有的
function subtract(num1,num2){
return num1 - num2;
}
//定義一個函數...
function multiply(num1,num2){
return num1 * num2;
}
//...以後將它導出
export multiply;複製代碼
在這個示例中須要注意幾個細節,除了 export
關鍵字外,每個聲明與腳本中的如出一轍。由於導出的函數和類聲明須要有一個名稱,因此代碼中的每個函數或類也確實有這個名稱。除非用 default
關鍵字,不然不能用這個語法導出匿名函數或類(隨後在「模塊的默認值」中會詳細講解)。this
另外,咱們看 multiply()
函數,在定義它時沒有立刻導出它。因爲沒必要老是導出聲明,能夠導出引用,所以這段代碼能夠運行。此外,請注意,這個示例並未導出 subtract()
函數,任何未顯示導出的變量、函數或類都是模塊私有的,沒法從模塊外部訪問。spa
從模塊中導出的功能能夠經過 import
關鍵字在另外一個模塊中訪問, import
語句的兩個部分分別是: 要導入的標識符和標識符應當從哪一個模塊導入。code
import { identifier1, identifier2 } from "./example.js";複製代碼
import
後面的大括號表示從給定模塊導入的綁定,關鍵字 from
表示從哪一個模塊導入給定的模塊,該模塊由表示模塊路徑的字符串指定(被稱做模塊說明符)。瀏覽器使用的路徑格式與傳統 ip