模块机制
JavaScript
的模块机制其实是借鉴的其他程序设计语言的。JavaScript
在设计之初并没有提供类似模块的功能,随后在ES5时代出现了各种模拟类似的功能模范,并且在ES6中新增了模块机制。模块机制就是将逻辑上相关的代码组织到同一个包内,包内是一个相对独立的作用域,不用担心命名冲突等等, 当需要在外部使用时直接import相应的package即可。
无模块化的缺陷
- 污染全局作用域
- 维护成本高
- 依赖关系不明显
CommonJS(NodeJS)
CommonJS:通用模块规范,由NodeJS实现。根据CommonJS规范, 一个单独的文件就是一个模块。每一个模块都是一个单独的作用域, 也就是说, 在该模块内部定义的变量, 无法被其他模块读取, 除非定义为global(浏览器中为window)对象的属性。
//模块定义 myModule.js
var name = 'Byron';
function printName(){
console.log(name);
}
function printFullName(firstName){
console.log(firstName + name);
}
module.exports = {
printName: printName,
printFullName: printFullName
}
//加载模块
var myModule = require('./myModule.js');
myModule.printName();
AMD(RequireJS)
AMD:Asynchronous Module Definition(异步模块定义), 在浏览器端模块化开发的规范, 不是JavaScript原生支持, RequireJS是AMD规范的具体实现(严格上说是RequireJS的推广中产生的AMD规范)。
// 定义模块 myModule.js
define('myModule', ['dependency'], function(){
var name = 'Byron';
function printName(){
console.log(name);
}
return {
printName: printName
};
});
// 加载模块
require(['myModule'], function (my){
my.printName();
});
CMD(SeaJS)
CMD: Common Module Definition通用模块定义, 由国内发展出来, SeaJS是其典型代表, 即SeaJS是通过浏览器对CMD的具体实现
// 定义模块 myModule.js
define(function(require, exports, module) {
var $ = require('jquery.js');
var foo = require('foo');
var out = foo.bar();
$('div').addClass('active');
module.exports = out;
});
// 加载模块
seajs.use(['myModule.js'], function(my){
});
ES6模块(import,export)
ES6在语言标准的层面上, 实现了模块功能, 而且实现得相当简单, 完全可以取代CommonJS
和AMD
规范, 是浏览器和服务器通用的模块解决方案。
在ES6中每一个模块即是一个文件,在文件中定义的变量,函数,对象在外部是无法获取的。如果你希望外部可以读取模块当中的内容,就必须使用export来对其进行暴露(输出)。(严格模式)
导出:
export:可以有多个,导出的数据在被引入时必须加{}
export default:一个文件中只能出现一次,引入时不需要{}
引入:import
//模块定义 myModule.js
const name = 'Byron';
function printName(){
console.log(name);
}
function printFullName(firstName){
console.log(firstName + name);
}
const myModule = {
printName: printName,
printFullName: printFullName
};
export myModule;
//加载模块
import myModule, { printFullName } from './myModule.js';
myModule.printName();
printFullName('Michael');
对比
CommonJS | AMD | CMD | ES6模块 | |
---|---|---|---|---|
适用于 | 服务端(node) | 浏览器端 | 浏览器端(依赖就近、延迟执行) | 服务端/浏览器端 |
如何使用 |
module.exports 定义当前模块对外输出的接口;require 加载模块 |
define 定义一个模块;require 加载一个模块;require.config() 指定引用路径 |
define 定义一个模块;require 加载一个模块 |
export 导出模块;import 引入模块 |
加载方式 | 同步 | 异步/依赖前置、提前执行 | 异步/依赖就近、延迟执行 | 异步 |
优点 | 解决了依赖、全局变量污染的问题 | 适合在浏览器环境中异步加载模块、并行加载多个模块 | 按需加载、节约开发成本 | 在浏览器和服务端都适用;编译时即可完成模块加载,效率更高 |
缺点 | 同步加载模式只适用于服务端;在浏览器端,限于网络原因,应使用异步加载 | 不能按需加载、开发成本大、影响用户体验 |
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。