有时我会遇到某些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']
中的依赖项加载。< / p>
我熟悉AMD模块,但看到这一点让我想知道如果我写一个具有依赖关系的库,我是否应该使用相同的模式,或者每次都应该使用这种模式,即使我没有依赖关系一点都不。
答案 0 :(得分:1)
这称为universal module definition模式。它有无数的变化。它的核心是JavaScript没有内置模块系统(直到ES6 modules被广泛采用)并且有很多这些系统可以填补空白(例如requirejs,yepnope, labjs)。因此,UMD是为了让您的模块在多个环境中支持模块系统而构思的模式,因为JavaScript现在几乎在所有地方都在使用。
在您的示例中,您将支持了解Asynchronous Module Definition,CommonJS模块加载器的脚本加载器,例如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, _, $)
使用这个样板代码,您可以编写一次模块,同时可以在浏览器,服务器和其他任何可能找到JavaScript环境的地方使用不同的加载器/构建工具。
我建议您阅读JavaScript模块/模块系统以获得更深入的了解。 Addy osmani's blog也是一个很好的起点。这个主题有很多资源。
希望这有帮助!快乐的编码。