CommonJS, AMD, CMD 和 原生 JS 一些感悟
pfan123 opened this issue · 0 comments
CommonJS, AMD, CMD 和 原生 JS 一些感悟
模块标准
CommonJS
Node应用由模块组成,采用CommonJS模块规范。
根据这个规范,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
如果想要对外提供接口的话,可以将接口绑定到 exports (即 module.exports) 上,推荐使用 module.exports(一个页面代表一个模块)。
CommandJS写法示例:
//先创建一个 check_commonjs.js 的文件
var flag = true;
function check(){
return flag;
}
module.exports = check
//在我们需要用到的页面加载模块
var check = require('./check_commonjs');
check()
CommonJS是用在Node应用中的模块规范,在做web开发中并不被前端开发人员所追逐,由于Node作为服务端应用,加载一个文件,速度就是真的是可以忽略不计的,然而浏览器作为一个客户端,在这个大框框下面,想要加载完一个js文件,再执行下面的js语句,加载时间速度真没那么快,所以就有了我们常用的AMD和CMD
AMD
随着RequireJS成为最流行的实现方式,异步模块规范(AMD)在前端界已经被广泛认同。
RequireJS的例子:
// 先创建一个 check_amd.js 的文件
define(['check'], function(){
var flag = true;
function check(){
return flag;
}
return {
check: check
};
});
// 在我们需要用到的页面加载模块
require(['check_amd'], function (check){
if(check.check()){
console.log("哈哈哈");
}
});
从代码的整洁性和可读性来讲, CommonJS 要好很多, 但AMD定义下的RequireJS 解决了上述同步加载文件导致的问题
CMD
CMD 通用模块定义最常见的应用例子就是SeaJS, 有些人把RequireJS 与 SeaJS做比较的时候, 会简单的认为异步与同步的区别
这是不太对, web端加载文件的时候一定是异步的
// 先创建一个 check_cmd.js 的文件
define(function(require, exports, module) {
var a = require('a');//这里就不举例再创建a文件了
function check(){
return a.flag;
}
exports.check = check;
});
// 在我们需要用到的页面加载模块
seajs.use(['check_cmd.js'], function(check){
if(check.check()){
console.log("哈哈哈");
}
});
CMD与AMD比较可以发现,AMD用户体验好由于没有延迟,依赖模块提前执行了,CMD性能好,因为只有用户需要的时候才执行。
在我们使用过程中,发现其实RequireJS和Sea.js在资源加载的时间点都是一样的,所以论“懒”的程度都是一样的。差别仅仅在于加载的脚本什么时候执行。RequireJS的依赖模块在回调函数执行前执行完毕,而Sea.js的依赖模块在回调函数执行require时执行。
ps: Sea.js原理
1.seajs中通过回调函数的Function.toString函数(真实使用parseDependencies(factory.toString())),使用正则表达式来捕捉内部的require字段,找到require('xx')内部依赖的模块xx
2.根据配置文件,找到jquery的js文件的实际路径
3.在dom中插入script标签,载入模块指定的js,绑定加载完成的事件,使得加载完成后将js文件绑定到require模块指定的id(这里就是jquery这个字符串)上回调函数内部依赖的js全部加载(暂不调用)完后,调用回调函数
兼容AMD、CMD、CommonJS,同时还支持老式的“全局”变量规范:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof define === 'function' && define.cmd) {
define(function(require, exports, module){
module.exports = factory()
});
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.LocalStorage = factory();
}
}(this, function () {
// 方法
function myFunc(){};
myFunc.prototype = {
constructor: "myFunc"
}
// 暴露公共方法
return myFunc;
})