代码改变世界

公共模块定义/草案(Common Module Definition / draft - CMD草案)

2017-08-12 22:16  盛世游侠  阅读(771)  评论(0编辑  收藏  举报

This specification addresses how modules should be written in order to be interoperable in browser-based environment. By implication, this specification defines the minimum features that a module system must provide in order to support interoperable modules.

  • Modules are singletons.
  • New free variables within the module scope should not be introduced.
  • Execution must be lazy.

Module Definition

A module is defined with define keyword, which is a function.

define(factory);
  1. The define function accepts a single argument, the module factory.
  2. The factory may be a function or other valid values.
  3. If factory is a function, the first three parameters of the function, if specified, must be "require", "exports", and "module", in that order.
  4. If factory is not a function, then the module's exports are set to that object.

Module Context

In a module, there are three free variables: requireexports and module.

define(function(require, exports, module) {

  // The module code goes here

});

The require Function

  1. require is a function

    1. require accepts a module identifier.
    2. require returns the exported API of the foreign module.
    3. If requested module cannot be returned, require should return null.
  2. require.async is a function

    1. require.async accepts a list of module identifiers and a optional callback function.
    2. The callback function receives module exports as function arguments, listed in the same order as the order in the first argument.
    3. If requested module cannot be returned, the callback should receive null correspondingly.

The exports Object

In a module, there is a free variable called "exports", that is an object that the module may add its API to as it executes.

The module Object

  1. module.uri

    The full resolved uri to the module.

  2. module.dependencies

    A list of module identifiers that required by the module.

  3. module.exports

    The exported API of the module. It is the same as exports object. 

Module Identifier

  1. A module identifier is and must be a literal string.
  2. Module identifiers may not have a filename extensions like .js.
  3. Module identifiers should be dash-joined string, such as foo-bar.
  4. Module identifiers can be a relative path, like ./foo and ../bar.

Sample Code

A typical sample

math.js

define(function(require, exports, module) {
  exports.add = function() {
    var sum = 0, i = 0, args = arguments, l = args.length;
    while (i < l) {
      sum += args[i++];
    }
    return sum;
  };
});

 

increment.js

define(function(require, exports, module) {
  var add = require('math').add;
  exports.increment = function(val) {
    return add(val, 1);
  };
});

 

program.js

define(function(require, exports, module) {
  var inc = require('increment').increment;
  var a = 1;
  inc(a); // 2

  module.id == "program";
});

 

Wrapped modules with non-function factory

object-data.js

define({
    foo: "bar"
});

 

array-data.js

define([
    'foo',
    'bar'
]);

 

string-data.js

define('foo bar');

 

 

 

译文:

本规范阐述了如何编写模块,以便在基于浏览器的环境中进行互操作。本规范定义了模块系统必须提供的最小功能,以支持互操作模块。

  • 模块应该是单例。
  • 不应引入模块作用域范围内的新的自由变量。(模块作用域范围内不应引入新的自由变量)(其他模块不应引入模块作用域范围内的新的自由变量)
  • 执行必须是懒惰的。

模块定义

一个模块就是一个函数,使用“define”关键字定义。

例如:

define(factory);

define函数接受单个参数,即模块工厂。

工厂可能是一个函数或其他有效值。
如果factory是一个函数,函数的前三个参数(如果指定的话)必须是“require”,“exports”和“module”。
如果工厂不是一个函数(不是函数那必然就是对象或者基本类型了),那么模块的export属性应该设置为该对象(这里这个“对象”两个字,意思是“那个传入模块的单个参数,即模块工程,因为它不是函数,那么可能是js对象或者js基本类型)。

模块上下文 

一个模块中有三个自由变量:require,exports 和 module。

例如:

define(function(require, exports, module) {

  // The module code goes here

});

require函数

1. ”require“是一个这样的函数:

  1. require 函数接收一个模块标识符(模块标识符也叫模块id)。
  2. require 函数返回外部模块的导出API(”导出API“是用来导出内容给外部模块使用的)。
  3. 如果无法返回请求的模块, require 函数将返回null。

2. ”require.async“ 是一个这样的函数:

  1. require.async 接收一个模块Id列表和一个可选的回调函数。
  2. 回调函数接收模块导出作为函数参数,按照与第一个参数中的顺序相同的顺序列出。
  3. 如果不能返回请求的模块,则回调应该相应地收到null。

exports对象

每个模块中都有个名叫"exports"的自由变量,这是一个模块可以在模块执行时添加模块API的对象。

module对象

1. module.uri:完整解析的模块URI(模块URI的全路径)。

2. module.dependencies:模块请求的标识符(模块id)列表。

3. module.exports:模块的导出API(”导出API“是”用来导出什么东西的API“)。 它与export对象相同。

模块标识符(模块id)

  1. 模块的标识符(模块id)必须是字面量字符串。
  2. 模块标识符(模块id)不能有类似  .js 的文件名扩展
  3. 模块标识符(模块id)应该是加前/后缀的字符串,比如:foo-bar。
  4. 模块标识符(模块id)可以是相对路径,例如:  ./foo 和 ../bar.。

 

示例代码

一个典型的例子:

math.js

define(function(require, exports, module) {
  exports.add = function() {
    var sum = 0, i = 0, args = arguments, l = args.length;
    while (i < l) {
      sum += args[i++];
    }
    return sum;
  };
});

 

increment.js

define(function(require, exports, module) {
  var add = require('math').add;
  exports.increment = function(val) {
    return add(val, 1);
  };
});

 

program.js

define(function(require, exports, module) {
  var inc = require('increment').increment;
  var a = 1;
  inc(a); // 2

  module.id == "program";
});

 

使用非函数的工厂包装模块

object-data.js

define({
    foo: "bar"
});

 

array-data.js

define([
    'foo',
    'bar'
]);

 

string-data.js

define('foo bar');