Sea.js 手册与文档


目录


何为 CommonJS?

CommonJS 是一个有志于构建 JavaScript 生态圈的组织。它有一个 邮件列表,有很多开发者参与其中。 整个社区致力于提高 JavaScript 程序的可移植性和可交换性,无论是在服务端还是浏览器端。

何为 CommonJS 模块?

JavaScript 并没有内置模块系统(反正现在没有),于是 CommonJS 创造了自己的。 传统的 CommonJS 模块如下:

math.js:

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

increment.js:

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

program.js:

var inc = require('increment').increment;
var a = 1;
inc(a); // 2

为何封装模块?

仔细看上面的代码,您会注意到 require同步的。也就是说, 模块系统需要在 require 方法调用返回 之前,就能判定给定模块是否可用(并初始化它)。

然而,这在浏览器端问题多多。

浏览器端,加载 JavaScript 最佳、最容易的方式是在 document 中插入 <script> 标签。但脚本标签天生异步,传统 CommonJS 模块在此类环境中无法正常加载。

解决思路之一是,开发一个服务器端组件,对模块代码作静态分析,将模块与它的依赖列表一起返回给浏览器端。 这很好使,但需要安装额外的组件,并因此要调整一系列底层架构。

另一种解决思路是,用一套标准模板来封装模块定义:

define(function(require, exports, module) {

  // The module code goes here

});

这套模板代码为模块加载器提供了机会,使其能在模块代码执行之前,对模块代码进行静态分析,并动态生成依赖列表。

为了让静态分析可行,需要遵守一些简单的 规则

把上面例子中的模块封装起来,可得到:

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

若干说明源自 FlyScript 的文档。 非常感谢 Kevin H. Smith。