Javascript 具有依赖关系的库的模式

Javascript pattern for library with dependencies

有时我会遇到某些 javascript 库中存在的特定模式。也许这是巧合,但我在具有依赖关系的库中看到过它。语法如下(示例取自Backbone,它对下划线有硬依赖)

(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
            root.Backbone = factory(root, exports, _, $);
        });
  } else if (typeof exports !== 'undefined') {
      var _ = require('underscore');
      factory(root, exports, _);
  } else {
      root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
  }

}(this, function(root, Backbone, _, $)

谁能解释一下为什么使用这种模式。我不太了解的部分是 factory 变量的使用,为什么要测试 属性 define.amd 以及为什么导出作为 define(['underscore', 'jquery', 'exports'] 中的依赖项加载.

我熟悉 AMD 模块,但看到这让我想知道如果我正在编写一个具有依赖性的库,我是否应该使用相同的模式,或者即使我根本没有依赖性,也应该每次都使用这种模式.

要点

这叫做universal module definition pattern. It comes in countless variations. The core of it is that JavaScript has no builtin module system (up until ES6 modules become widely adopted) and there are numerous of these out there to fill the gap (e.g. requirejs, yepnope, labjs)。因此,UMD 是一种模式,旨在让您的模块支持多种环境中的模块系统,因为 JavaScript 现在几乎无处不在。

你的例子

在您的示例中,您将支持理解引入的 Asynchronous Module Definition, CommonJS module loaders like the one that NodeJS 的脚本加载器以及普通浏览器或其他不公开定义所知道的模块系统的环境:

(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        // This branch is to support AMD loaders
        define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
            root.Backbone = factory(root, exports, _, $);
        });
  } else if (typeof exports !== 'undefined') {
      // This supports the CommonJS module system that NodeJS uses
      var _ = require('underscore');
      factory(root, exports, _);
  } else {
      // Attaching your library root in an environment that has no
      // module system or a system you don't support like a plain
      // browser before ES6 modules become the standard
      root.Backbone = /* ... */
  }

}(this, function(root, Backbone, _, $)

使用此样板代码,您可以编写一次模块,同时可以在浏览器、服务器和其他任何地方使用不同的 loaders/build 工具,您可能会发现 JavaScript 环境.

我建议您阅读 JavaScript modules/module 系统以获得更深入的了解。 Addy osmani's blog 也是一个很好的起点。有许多关于该主题的资源。

希望对您有所帮助!编码愉快。