模块化是指将一个复杂的系统分解为多个模块,方便编码,同时下降代码复杂性,下降代码耦合度,方便部署,提升效率,避免了命名冲突,也能够减小变量空间污染,更好的分离代码,方便按需加载,更高的复用性,更高的可维护性。常见的模块化有CommonJs、AMD、CMD、ES6
,下面就分别来介绍他们。html
CommonJs
CommonJs
将每一个javaScript
文件看成是一个模块, 其内部定义的变量函数等都属于这个模块,咱们能够向外部暴露咱们想要暴露的。可是CommonJs
必须在node
环境下才能使用,它是为node
而生的,只有使用node环境才能运行,而浏览器是不支持CommonJs
的,必须使用一些转换工具,将咱们服务器端的CommonJs
语法转化为浏览器识别的语法。java
在CommonJs
中,每个javaScript
文件都会隐士的被包裹在一个当即函数里面,例以下面的例子node
var name = 'xxx' module.exports = { name: name }
最终会被转换成下面这个样子api
(function(exports, require, module, __filename, __dirname){ var name = 'xxx' module.export = { name: name } })
exports、 require、 module、 __filename、 __dirname
exports
和module.exports
实际上是一个东西,只不过须要注意使用exports
不能改变它的指向。require
是用来引入咱们须要的外部模块的,他是同步加载的,适用于服务器端。__filename
和__dirname
分别是当前执行的文件路径和文件夹路径。浏览器
CommonJs
通常咱们能够直接使用node 文件名
直接将文件置于node环境运行,这样是彻底ok的。可是假若咱们须要将它放到浏览器端运行,也就是引入到html
文件中,因为浏览器是不认识前面咱们说的exports、require...
这些语法的,因此咱们能够借助像Browserify
这样的转换工具。咱们看下面的例子服务器
// m1.js module.exports = { name: 'xxx' } // m2.js module.exports = { age: '100' } // main.js const name = require('m1') const age = require('m2') console.log(name, age) // index.html ... <script src="./node_modules/main.js"></script> ...
当咱们打开html的时候浏览器是会报错的,以下babel
Uncaught ReferenceError: require is not defined at main.js:1
咱们能够借助Browserify,将Browserify
下载下来,将咱们的main.js
使用它转换后,将转换后的文件引入页面中,修改后咱们就能正常运行了,修改后的html代码以下网络
<script src="./node_modules/bundle.js"></script>
browerify
用法很简单,能够看它的文档异步
AMD
CommonJs
为服务器端而生,采用的同步加载方式。所以不适用浏览器。由于浏览器须要到服务器加载文件,请求时间远大于本机读取的时间,假若文件较多,网络迟缓就会致使页面瘫痪,因此浏览器更但愿可以时间异步加载的方式。
而AMD
规范则是异步加载模块,容许指定回调函数。等模块异步加载完成后便可调用回调函数。它依赖一个库require.js,这里就简单的说一下它的用法,具体请参考文档。AMD
的核心思想就是经过define
来定义一个模块,而后使用require
来加载一个模块。
``async
define
基本使用define(moduleId,['module1','mdule2'],function(m1,m 2){...});
moduleId
为当前定义的模块ID,若是不写默认是当前文件名,module1
等是咱们要引入的模块的ID
,func
的参数就是导入的模块例如m1
就是module1
导入的变量,以后咱们使用m1
就行,须要注意的是若是咱们要像module.exports
同样向外暴露变量等,咱们须要在每一个模块的func
中返回咱们须要暴露的东西
require
在咱们须要定义模块的地方使用define,当咱们须要使用这些暴露的模块的时候,使用require(['module1','module2'],function(m1, m2) {...})
在func
中写咱们的代码
同时须要在最上面配置一下咱们须要引入的模块的路径以及它涉及到的模块的路径使用require.config({paths: { 模块一: 路径,模块二: 路径}})
下面给一个简单的AMD例子
// m1.js define(function() { return { name: 'xxx' } }); // m2.js define(function() { return { age: '100' } }); // main.js require.config({ path: { m1: './m1.js', m2: './m2.js' } }) require(['m1', 'm2'], function (m1, m2) { console.log(m1.name, m2.age) }) // index.html ... <script src="./node_modules/require.js" data-main="./node_modules/main.js"></script> ...
CMD
CMD
异步加载,跟AMD
的主要区别在于,AMD
依赖前置,提早加载依赖。而CMD
就近加载,按需加载。
产物seaJs,跟requireJs
使用有些类似。
若是咱们想使用SeaJS
,咱们只须要将其引入到咱们的页面中,而后使用seajs.use('入口文件')
,咱们就能够在咱们的入口文件中使用咱们的CMD
了CMD
的核心思想就是经过define
来定义一个模块,而后使用require
来加载一个模块,听起来和AMD
有点相似,可是实际的使用仍是有区别的。
define
当咱们在一个文件中定义一个模块的时候,能够像下面这样
define(function(require,exports,module){ module.exports = {} })
require
require
在CMD
中分为同步和异步下面分别给出同步和异步使用的方式
// 同步 var module = require('xxx') //异步 var module = require.async('m1', function(m1){ ... })
ES6
ES6
自带模块化,可使用 import
关键字引入模块,经过 export
关键字导出模块,功能较之于前几个方案更为强大,也是咱们所推崇的,可是因为ES6
目前没法在浏览器中执行,因此,咱们只能经过babel
将不被支持的import
编译为当前受到普遍支持的 require
。