模块化的意义: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后,动态加载的优点就会展示: