正文
一、模块的重要性
Javascript不是一种模块化编程语言,它不支持”类”(class),更别说”模块”(module)了。开发者们做了很多努力,在现有的运行环境中,实现”模块”的效果。
没有模块的日子里
function a(){
...
};
function b(){
...
};
function c(){
...
};
后果:
-
全局变量的灾难;
-
函数命名冲突;
-
依赖关系不好管理。
js模块的前身(为了解决以上问题)
1. 面对对象的写法:
var obj = {
a:1,
b:function(){
...
}
};
优点:
1、解决了变量污染的问题;
2、保证模块名唯一即可,建立同一模块内的成员的关系。
缺点:
1、暴露所有模块成员,内部状态可以被外部任意改写。
obj.a =100;
2. 匿名自执行函数:
(function(){
var obj = {
a:1,
b:function(){
...
}
};
})();
优点:
1、解决暴露所有模块成员,内部状态可以被外部任意改写的问题。
缺点:
1、所需依赖还是得外部提前提供。
二、commonJS
2009年,对js是历史性的一年,nodeJS横空出世,让js跑在服务端,如果说js在浏览器上面可以没有模块,但是在服务端没有模块的思想是万万不能容忍的。由Mozilla 的工程师 Kevin Dangoor 在2009年1月创建了commonJS规范。
//创建模块 one.js
var a = 'aaaa';
function b(){
console.log(a);
};
module.exports = {
a: a,
b: b
};
//加载模块 two.js
var x = require('./one.js');
x.b();
优点:
1、所有代码都运行在模块作用域,不会污染全局作用域;
2、独立性是模块的重要特点就,模块内部最好不与程序的其他部分直接交互;
3、模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存;
4、模块加载的顺序,按照其在代码中出现的顺序。
node推广了commonJS规范,但是在浏览器中又出现了很多问题
问题:
浏览器资源的加载方式与服务端完全不同。服务端require一个模块,直接就从硬盘或者内存中读取了,消耗的时间可以忽略。而浏览器则不同,需要从服务端来下载这个文件,然后运行里面的代码才能得到API,需要花费一个http请求,也就是说,require后面的一行代码,需要资源请求完成才能执行。
由于浏览器端是以插入script标签的形式来加载资源的(ajax方式不行,有跨域问题)没办法让代码同步执行,所以像commonjs那样的写法会直接报错。
这意味着要想适应浏览器,规范还要改进!!!
一个
Modules/Wrappings
规范出现了。
三、AMD
经过一番谈论、修改(过程忽略),AMD思想出现了…AMD(Asynchronous Module Definition):
-
异步模块定义规范制定了定义模块的规则,这样模块和模块的依赖可以被异步加载。这和浏览器的异步加载模块的环境刚好适应(浏览器同步加载模块会导致性能、可用性、调试和跨域访问等问题)。
-
依赖前置,预执行(异步加载:依赖先执行,依赖必须一开始就写好,会先尽早地执行(依赖)模块 。换句话说,所有的require都被提前执行(require 可以是全局或局部 )。
相关Api(简单实例):
//定义和暴露模块
define("xxx", ["xxx", "xxx"], function(x, x) {
return ... ;
});
//加载模块
require(["xxx", "../xxx"], function(xxx, xxx) {
xxxx
});
具体Api请参见:
AMD (中文版)
RequireJS
说完AMD,就不得不提把AMD在浏览器实现的RequireJS。
RequireJS是一个JavaScript文件和模块加载器,采用AMD规范。
参考文件:
RequireJS
三、CMD
CMD(Common Module Definition):