Simplified CommonJS wrapper 与 AMD 标准定义模块差别

标准的 AMD 模块定义

一个标准的 AMD 模块看起来是这样子:git

define(['foo', 'foo/bar'], function (foo, bar) {
    return {
        doSomething: function () {
            console.log(foo + bar);
        }
    };
});

模块 foofoo/bar 在工厂函数被调用以前完成加载,并做为参数传递给工厂函数。github

工做原理:数组

  1. RequireJS 读取依赖模块数组。
  2. 继而检查当前上下文是否已注册这些依赖模块:
    1. 若是模块已注册,则直接使用;
    2. 不然:
      1. 经过检查 paths.config 和当前模块路径,将模块 ID 解析为 URI。
      2. 加载 URI 指向的源文件。
      3. 若是依赖模块是 AMD 模块,则重复以上过程直至全部依赖模块被加载完毕。
  3. 当全部依赖模块准备稳当,将依赖模块做为参数去调用工厂函数,工厂函数的返回值做为新模块被注册到当前上下文。

Simplified CommonJS wrapper

若是你想让别人像 CommonJS 模块那样使用你的模块,尤为是你的模块拥有大量依赖模块,你可使用 Simplified CommonJS wrapper。app

define (function (require, exports, module) {
    var foo = require('foo'),
          bar = require('foo/bar');

    exports.doSomething = function () {
        console.log(foo + bar);
    };
});

一个模块被当作 CommonJS 模块,它必须不能包含依赖模块数组,而且工厂函数包含至少一个参数。函数

工做原理:requirejs

  1. RequireJS 检查 define 函数调用是否没有使用依赖模块数组。
  2. 而后经过读取 Function.prototype.length 来检查工厂是否接受参数。
    1. 若是接受参数,则将该模块视为 CommonJS 模块:
      1. 调用 Function.prototype.toString(),并找到全部工厂函数中全部同步的 require() 调用来肯定依赖模块。
      2. 加载全部依赖模块。
      3. 完成依赖模块加载后,将特殊模块 require, exportsmodule 做为参数传递给工厂函数,而后将函数返回值或 module.exportsexports 注册为新模块。
    2. 若是不接受参数,则将该模块视为标准 AMD 模块(没有依赖包),执行工厂函数并注册函数返回值为新模块。

同步 require()

对于一个标准的 AMD 模块,只要模块在当前上下文注册,你能够同步调用 require() 函数。ui

define (['require', 'lorem/ipsum'], function (require) {
    // 由于模块 lorem/ipsum 在依赖数组中。
    // 它会在工厂函数被调用前完成注册,所以本段代码是可行的。
    console.log(require('lorem/ipsum'));
});

但如下代码会由于 dolor/amet 未注册而失败:prototype

define(['require'], function (require) {
    console.log(require('dolor/amet'));
});

由于咱们在 define 函数中使用了依赖数组,所以新模块将被视为标准 AMD 模块,所以它不会扫描工厂函数代码以获取依赖数组。你将看到如下异常提示:code

Uncaught Error: Module name 'dolor/amet' has not been loaded yet for context: _接口

若是使用 Simplified CommonJS Wrapper,那么 RequireJS 会在工厂函数调用前加载依赖包:

define (function (require) {
    console.log(require('dolor/amet'));
});

特殊模块

标准 AMD 模块中一样可使用特殊模块 require, exportsmodule

exports

define (['exports'], function (exports) {
    exports.foo = 'bar';
    exports.lorem = function (){
        console.log('ipsum');
    };
});

添加到 exports 上的属性会自动成为模块的公开接口,工厂函数无需返回值。

module

如下模块记录了模块 ID 和当前模块的路径。

define (['module'], function (module){
    console.log(module.id);
    console.log(module.uri);
});

require

require 模块除了能够加载依赖模块,还能够指出模块源文件路径。

  • require.toUrl(moduleName): 返回模块源文件路径。

PS:本文译自 Differences between the Simplified CommonJS wrapper and standard AMD define

相关文章
相关标签/搜索