JS模块化规范

日期:2017-06-15       浏览:629

一 CommonJS

CommonJS 原来叫 ServerJS ,是以在浏览器环境之外构建 JavaScript 生态系统为目标而产生的项目,比如在服务器和桌面环境中。CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。该规范的主要内容是,模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。例子如下:
// moduleA.js
module.exports = function(x) {
    return x * x; 
};
// moduleB.js
const moduleA = require('./moduleA');
var result = moduleA(2);
CommonJS 是同步加载模块。
NodeJs就是采用commonJs规范。

二 AMD

AMD(Asynchronous Module Definition) (异步模块定义)是为浏览器环境设计的,因为 CommonJS 模块系统是同步加载的,当前浏览器环境还没有准备好同步加载模块的条件。AMD 定义了一套 JavaScript 模块依赖异步加载标准,来解决同步加载的问题。模块通过 define 函数定义在闭包中,格式如下:
define(id?: String, dependencies?: String[], factory: Function|Object);
id 是模块的名字,它是可选的参数。dependencies 指定了所要依赖的模块列表,它是一个数组,也是可选的参数,每个依赖的模块的输出将作为参数一次传入 factory 中。如果没有指定 dependencies,那么它的默认值是 ["require", "exports", "module"]。
define(function(require, exports, module) {})
factory 是最后一个参数,它包裹了模块的具体实现,它是一个函数或者对象。如果是函数,那么它的返回值就是模块的输出接口或值。定义一个名为 moduleA 的模块,它依赖 jQuery 模块:
define('moduleA', ['jquery'], function($) {
    // $ 是 jquery 模块的输出
    $('body').text('hello world');
});
// 使用
define(['moduleA'], function(moduleA) {});
RequireJS就是采用AMD规范。

三 CMD

CMD(Common Module Definition),在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:
define(factory);
define是全局函数,用来定义模块。define接收factory参数,factory可以是函数,对象或字符串。factory为对象或字符串时,表示该模块的接口就是该对象或字符串,比如要定义一个json数据模块:
define({"key" : "val"});
也可以通过字符串定义模板模块:
define("Hello {{name}}!")
factory是函数时,表示是模块的构造方法。执行该构造方法,可以得到模块对外提供的接口,factory方法在执行时,默认会传入三个参数,require,exports,module。
define(function(require, exports, module) {
    // 需要导出的模块
});
require是方法,接收模板标识作为唯一参数,用来获取其他模块提供的接口:
define(function(require, exports) {
    const a = require('./a');
    a.doSomething();
});
require是同步往下执行的,require.async(id, callback?)用来在模块内部异步加载模块,并在加载完后执行回调函数:
define(function(require, exports) {
    require.async(['./a', './b'], function(c, d) {
        c.doSomething();
        d.doSomething();
    });
});
factory是函数时的第二个参数exports,exports是一个对象,用来对外提供模块接口。
define(function(require, exports) {
    exports.str = 'xxxxx';  // 对外提供str属性
    
    exports.doSomething = function() {  // 对外提供 doSomething() 方法
        // TODO
    };
});
除了exports外,还可以用return直接对外提供对象接口
define(function(require, exports) {
    return {
        str : 'xxxxx' ,
        doSomething : function() {}
    };
});
exports是module.exports对象的一个引用,很多时候exports都无法满足要求,例如对外提供一个实例对象:
define(function(require, exports, module) {
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    module.exports = new Person('lily', 20); // 对外提供实例化后的Person对象。
});
module.exports还可以对外提供一个函数(exports不可以):
define(function(require, exports, module) {
    var Person = function(name, age) {
        this.name = name;
        this.age = age;
    }
    module.exports = Person; // 对外提供Person函数。
});
sea.js就是采用CMD规范。

四 AMD+CMD比较

AMD默认是依赖前置,在一开始就将需要依赖的文件配置并加载好:
define('moduleA', ['jquery'], function($) {
    // 依赖的配置文件已经配置并加载好了。
    $('body').text('hello world');
});
CMD是依赖就近,需要使用的时候才会去配置加载:
define(function(require, exports) {
    var a = require('./a.js'); // 配置并加载,同步
    
    if(false) {
        var b = require('./b.js'); // 该配置的文件永远不会去加载,
    }
});
扫码关注有惊喜

(转载本站文章请注明作者和出处 qbian)

暂无评论

Copyright 2016 qbian. All Rights Reserved.

文章目录