pfan123/Articles

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;	
})

CommonJS规范
seajs
requirejs
LABjs、RequireJS、SeaJS 哪个最好用?为什么?