现在的位置: 首页 > 综合 > 正文

SeaJS 中的 exports 和模块加载

2018年08月17日 ⁄ 综合 ⁄ 共 1770字 ⁄ 字号 评论关闭

exports

首先是 exports 的几种形式,我们可以: 

define(function(require, exports, module) {
  exports.a = 'a';
  exports.fn = function() {};
});

也可以: 

define(function(require, exports, module) {
  module.exports = {
    a: 'a',
    fn: function() {}
  };
});

这两者有什么区别呢?

  1. 就最终的效果而言,这两种形式没什么区别:都是使得该模块对外提供 xx 和 fn 两个公共成员。
  2. 就代码组织形式而言, exports.xx
    = ...
     是分散赋值,中间可以穿插其他代码,很灵活。 module.exports
    = { ... }
     则是集中式赋值,便于管理。两种形式各有优劣,采用何种方式,很大程度上取决于个人喜好。
  3. 就内部实现而言,在传入参数时, exports
    = module.exports = {}
     , 很明显,第一种方式复用了 {} 初始值,第二种则给
    module.exports 重新赋了一个新对象。由于 require('module-id') 返回的是 module.exports ,
    因此最终的效果两种形式是一致的。
  4. 更直观的一种形式是 exports
    = { ... }
     , 但由于 JavaScript 里只能传值,不能传引用,直接给 exports 赋值,外面无法获取到 exports 的新值,因此才有了退而求其次的 module.exports
    = { ... }
     形式。

模块书写格式与模块加载器

在 seajs 里,“加载”一个模块可以有: 

seajs.use('a', callback);
require('a');
module.load('a', callback);

首先, seajs.use 仅用来在页面中加载起始入口模块,这就如我们在
nodejs 里,运行模块的入口是: 

node filename.js

seajs.use('a', callback) 就相当于 node
filename.js
 , 仅起到 bootstrap 的作用。

在标准模块里,推荐永远不要出现 seajs. 就如 nodeJS 的模块里,不会出现 node 一样。标准模块的书写形式为: 

define(function(require, exports, module) {
  // module code
});

这样做的好处,可以使得模块和具体加载器无关。比如 SeaJS 能加载的模块,理论上用 RequireJS 也可以跑起来,因为遵循的模块书写规范有很大交集。CommonJS 社区的一个目标就是使得各种环境下,都遵循统一的模块书写格式。这样,SeaJS, RequireJS, nodeJS 等都只是模块加载器,只要遵循的模块书写规范一致,模块就可以通用。

动态加载

define(function(require, exports, module) {
  var a = require('a');
  // ...
  module.load('b', function(b) {
    // ...
  });
  // ...
});

上面的代码, require('a') 对应的 a.js
模块在 require 执行前就已下载好,require('a') 仅执行
a.js 模块里 define 的 function 参数,以获取模块 a 的 exports. 这种方式是预先加载、按需执行。

而 module.load('b', callback) 是执行到此处时,才开始下载
b.js 模块。下载好后,回调 callback 函数。这种方式是动态延迟加载。

一般来说, require('a') 这种形式用于强依赖,缺了模块
a, 该模块功能就不全了。 module.load 则用于加载可选模块,比如在某些特定条件下才需要的功能。

这两种方式各自的使用场景不同,得具体问题具体分析。

有心人可以发现: module.load 和 seajs.use 是很类似的。内部实现上也的确是公用一套逻辑,唯一不同的是, module.load('path/to/module') 是相对当前模块来定位, seajs.use 是相对当前页面。

总结

目前的 API 设计,已尽量简化,尽量简明易懂。大家有什么好的想法和改进建议,非常欢迎反馈。(建议通过邮件或博客回复给我反馈,文档下面的 DISQUS 很慢,经常漏掉,不可靠。)

抱歉!评论已关闭.