javascript
工具(瀏覽器兼容)vue
組件(功能模塊)java
框架(功能模塊組織)node
應用(業務模塊組織)es6
可是通過了長長的後天努力過程JavaScript不斷被類聚抽象,以更好的組織業務邏輯。從另外一個角度而言,他也道出了JavaScript先天就缺少的一項功能:模塊數據庫
雖然W3C組織對HTML5規範推動以及各大廠對規範的大力支持,可是對於JavaScript自己而言,它的規範依然是薄弱的,它還有如下缺陷:瀏覽器
沒有標準模塊系統緩存
標準庫少(ECMAScript僅定義了部分核心庫)服務器
沒有標準接口(JavaScript幾乎沒有定義過如WEB服務器數據庫操做之類的標準統一接口)app
缺少包管理系統
CommonJS規範的提出,主要爲了彌補JavaScript沒有標準的缺陷,以達到想Python、Ruby和Java具有開發大型應用的基礎能力,而不是停留在小腳本程序的階段。
它的使用和定義也很是簡單
1 模塊定義
// example.js var x =5; var addx = function (value){ return value + x; } module.exports.x = x; module.exports.addx = addx;
定義關鍵字是exports這個module是什麼意思呢:在CommonJS定義了每一個文件都一個模塊,也就是說module表明文件自己
2 模塊引用
var example = require('./example.js'); console.log(example.x); // 5 console.log(example.addx(1)); // 6
CommonJS模塊特色以下:
模塊能夠屢次加載,可是隻會在第一次加載時運行一次,而後運行結果就被緩存了,之後再加載,就直接讀取緩存結果。要想讓模塊再次運行,必須清除緩存。
模塊加載的順序,按照其在代碼中出現的順序。
3 看圖
用一個圖很明顯的看出它們之間的引用關係
在Node中引入模塊,須要經歷3個步驟
一、路徑分析
二、文件定位
三、編譯執行
在Node中模塊分爲兩類:一類是Node提供的模塊,稱爲核心模塊;另外一類是用戶編寫的模塊稱爲文件模塊。
ES6 模塊的設計思想,是儘可能的靜態化,使得編譯時就能肯定模塊的依賴關係,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運行時肯定這些東西。好比,CommonJS 模塊就是對象,輸入時必須查找對象屬性。
// CommonJS模塊 let { stat, exists, readFile } = require('fs'); // 等同於 let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile;
上面代碼的實質是總體加載fs
模塊(即加載fs
的全部方法),生成一個對象(_fs
),而後再從這個對象上面讀取3個方法。這種加載稱爲「運行時加載」,由於只有運行時才能獲得這個對象,致使徹底沒辦法在編譯時作「靜態優化」。
ES6 模塊不是對象,而是經過export
命令顯式指定輸出的代碼,再經過import
命令輸入。
與CommonJS思想相似
1 模塊定義
// profile.js export var firstName = 'Michael'; export var lastName = 'Jackson'; export var year = 1958;
上面代碼是profile.js
文件,保存了用戶信息。ES6 將其視爲一個模塊,裏面用export
命令對外部輸出了三個變量。
export
的寫法,除了像上面這樣,還有另一種。
// profile.js var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; export {firstName, lastName, year};
一般狀況下,export
輸出的變量就是原本的名字,可是可使用as
關鍵字重命名。
function v1() { ... } function v2() { ... } export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion };
注意規範:
export
命令規定的是對外的接口,必須與模塊內部的變量創建一一對應關係。
// 報錯 export 1; // 報錯 var m = 1; export m;
上面兩種寫法都會報錯,由於沒有提供對外的接口。第一種寫法直接輸出1,第二種寫法經過變量m
,仍是直接輸出1。1
只是一個值,不是接口。正確的寫法是下面這樣。
// 寫法一 export var m = 1; // 寫法二 var m = 1; export {m}; // 寫法三 var n = 1; export {n as m};
function
和class
的輸出,也必須遵照這樣的寫法。
// 報錯 function f() {} export f; // 正確 export function f() {}; // 正確 function f() {} export {f};
另外,export
語句輸出的接口,與其對應的值是動態綁定關係,即經過該接口,能夠取到模塊內部實時的值。
2 模塊引用
// a.js let a = 18; let funcA = function () { console.log('module A') }; // 提供一個對外的藉口並輸出a變量和funcA方法 export {a, funcA}
引用
import {a, funcA} from "./a"; // 經過import 引入裏面的變量和方法 console.log(a); console.log(funcA());
引用的時候能夠設置別名
import {a as aValue, funcA} from "./a"; // 經過import 引入裏面的變量和方法 console.log(aValue); console.log(funcA());
3 export default命令
從前面的例子能夠看出,使用import
命令的時候,用戶須要知道所要加載的變量名或函數名,不然沒法加載。可是,用戶確定但願快速上手,未必願意閱讀文檔,去了解模塊有哪些屬性和方法。
爲了給用戶提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default
命令,爲模塊指定默認輸出。
本質上,export default
就是輸出一個叫作default
的變量或方法,而後系統容許你爲它取任意名字
// export-default.js export default function () { console.log('foo'); }
而後你能夠隨便命名
// import-default.js import customName from './export-default'; customName(); // 'foo'
可是正常引入模塊的狀況下你必須指定你要引入的變量或者方法,像下面同樣:
import {funcA} from "./a.js"; // 這裏你在引用的時候你必須知道a.js中定義的方法的名字
比較下正常和export default不一樣
// 第一組 export default function crc32() { // 輸出 // ... } import crc32 from 'crc32'; // 輸入 // 第二組 export function crc32() { // 輸出 // ... }; import {crc32} from 'crc32'; // 輸入
上面是模塊的語法,接下來看看如何在瀏覽器和Node中加載ES6模塊
在 HTML 網頁中,瀏覽器經過<script>
標籤加載 JavaScript 腳本
<!-- 頁面內嵌的腳本 --> <script type="application/javascript"> // module code </script> <!-- 外部腳本 --> <script type="application/javascript" src="path/to/myModule.js"> </script>
上面代碼中,因爲瀏覽器腳本的默認語言是 JavaScript,所以type="application/javascript"
能夠省略。
一樣若是你的目錄結構是這樣的:
你在本地安裝了node_js模塊vue的話一樣能夠直接經過script標籤引用
瀏覽器加載ES6模塊
瀏覽器加載 ES6 模塊,也使用<script>
標籤,可是要加入type="module"
屬性。
<script type="module" src="./foo.js"></script>
瀏覽器對於帶有type="module"
的<script>
,都是異步加載,不會形成堵塞瀏覽器,即等到整個頁面渲染完,再執行模塊腳本,等同於打開了<script>
標籤的defer
屬性。
<script type="module" src="./foo.js"></script> <!-- 等同於 --> <script type="module" src="./foo.js" defer></script>
ES6 模塊也容許內嵌在網頁中,語法行爲與加載外部腳本徹底一致。
<script type="module"> import utils from "./utils.js"; // other code </script>
參考資料:http://es6.ruanyifeng.com/#docs/module