模塊化的意義:html
ES6以前,JavaScript並無原生的模塊機制,好在JavaScript很是靈活,有不少種寫法能夠將代碼自然隔離,起到模塊化的功能:前端
//define var modules = {} modules.mod1 = { foo : function(){...}, bar : function(){...} ... } //call modules.mod1.foo()
在客戶端這種方式基本是夠用的,然而問題依然存在:你沒法管理依賴,全部的代碼都必須load到內存中,須要哪些模塊必須由人工處理。分模塊是工程化的產物,也是天然發展的結果,天然有不少嘗試。很顯然,模塊之間互相依賴須要編寫模塊的時候遵循必定的規範。現存的規範還真很多,不知道ES6 可否終結這場混戰:es6
AMD和CMD分別是requireJS和seaJS定義的標準。使用純原生的ES5語法意味者其只能使用閉包,書寫和閱讀都很怪異。值得一提的是AngularJS也使用相似的方式,以致於Angular的做者們都受不了,決定在AngularJS 2 使用新的語言AtScript,前端輪子太多,又造了一個,好在這個輪子造的比較好,兼容ES6 TypeScript規範,扯的遠了,看看AMD長得啥樣:web
AMD:gulp
define(['./a', './b'], function(a, b) { ... })
Closure是google出品的前端工具,Closure提供了一系列工具和庫,谷歌本身的多個項目都是使用Closure開發的。closure compiler經過模塊間依賴的聲明把全部被依賴的文件打包到一塊兒,並且Closure的一大優點是若是採用破壞性壓縮(ADVANCED)壓縮率極高。瀏覽器
//文件A goog.provide('module1') com.foo.bar = { ... } .... //文件B goog.require('module1') var a = com.foo.bar;
然而Closure並不完美,不一樣的文件共享同一個全局對象,因此你不得不這樣寫 a.b.c=…。服務器
CommonJS是Node.js使用的模塊化標準。Node.js對於前端開發者來講不只僅能夠提供一個Server,仍是一個完美的開發平臺,在Node上使用Grunt/gulp構建web項目是件很爽的事情。Node的模塊化聲明的方式與Closure相似,只是更進一步,自然隔離了命名空間。上面的代碼若是使用CommonJS的模塊化規範能夠這麼寫:閉包
//文件A module.exports = {...} .... //文件B var a = require('./foo/bar')
browserify讓使用CommonJS模塊化規範的代碼能夠運行在客戶端上。異步
在看ES6以前咱們先看模塊加載的兩種方式:ide
AMD標準是動態加載的表明,而CommonJS是靜態加載的表明。AMD的目的是用在瀏覽器上,因此是異步加載的。而NodeJS是運行在服務器上的,同步加載的方式顯然更容易被人接收,因此使用了CommonJS。一樣的道理,若是靜態加載,那就使用同步的加載方式,若是動態加載就必須用異步的加載方式。
那麼ES6採用何種加載機制?
ES6既但願用簡單的聲明方式來完成靜態加載,又不肯放棄動態加載的特性,而這兩種方式幾乎不可能簡單的同時實現,因此ES6提供了兩種獨立的模塊加載方法。
2.1 聲明的方式
import {foo} from module1
2.2 經過System.import API的方式
System.import('some_module') .then(some_module => { // Use some_module }) .catch(error => { ... });
再看下export的語法,與CommonJS很像,只不過沒有了module這個對象,而直接調用export。 能夠export任何一個 函數,變量,對象
//expt.js export function abc(){}//export 一個命名的function export default function(){} //export default function export num=123 //export 一個數值 export obj={} export { obj as default }; //import import expt from 'expt'//default export import {default as myModule} from 'expt' //rename import {abc,num,obj} from 'expt'
更多細節能夠看這篇文章:http://www.2ality.com/2014/09/es6-modules-final.html
目前來看,使用預編譯的方式顯然要好於使用動態加載,瀏覽器對ES6語法支持還不好,若是使用動態加載ES6,在瀏覽器端要作ES6到ES5的翻譯工做,這個顯然是重複低效的。可是隨着瀏覽器對ES6支持加強,尤爲是瀏覽器實現了動態加載API後,動態加載的優點就會展示: