我正在使用以下闭包模式来模块化我的代码:
(function(root) {
// MODULE CODE HERE
if (typeof module !== 'undefined' && module.exports) { // CommonJS
/* var dependencies = require(...) */
module.exports = myModule;
} else if (typeof define !== 'undefined' && define.amd) { // AMD
/* var dependencies...; */
define([/* dependencies */], function(/* dependencies */) {
/* Assign closure level vars to respective arguments */
return myModule;
});
} else {
// Dependencies??
root.myModule = myModule;
}
})(this);
即,我们使用特征检测来支持 CommonJS 模块(例如 node.js)、AMD 或基本的全局命名空间实例化。
这在 node.js 中运行良好;我还没有测试 AMD 模式,因为我还在阅读它(参见编辑 2:AMD 表现出完全相同的效果);但如果模块有任何依赖关系,它会在浏览器中失败。也就是说,如果myModule
引用了在不同模块中定义的内容:例如,假设我有super.js
并child.js
具有相应的模块定义,如上所述,其中super.js
创建一个名为root.super
(root === window
在浏览器中)的函数,如果child.js
尝试这样做super()
,我会得到类似的东西super is not a function
。
这里发生了什么?
为了尝试修复它,我更改了元素的加载顺序super.js
:child.js
没有<script>
运气。然后我尝试使用 jQuery 在文档准备好时强制child.js
加载:
$(document).ready(function() {
$.getScript('child.js', function() {
// Do stuff with child, which calls super
});
});
...再次,同样的问题。但是,在这两种情况下,如果我进入控制台,super
它就可用并按我的预期定义。
为什么可能来自不同super
的child.js
(即,不是全局的)范围?
我应该补充一点,如果我删除 CommonJS 导出中的依赖注入位,它会在 node.js 中失败并出现相同的错误(如果有任何依赖项)。
编辑@Amberlamps 的回答解决了这个问题,但它没有回答为什么会发生这种情况的问题。我的模块模式现在是:
(function(root) {
// MODULE CODE HERE
if (typeof module !== 'undefined' && module.exports) { // CommonJS
/* var dependencies = require(...) */
module.exports = myModule;
} else if (typeof define !== 'undefined' && define.amd) { // AMD
/* var dependencies...; */
define([/* dependencies */], function(/* dependencies */) {
/* Assign closure level vars to respective arguments */
return myModule;
});
} else {
if (root.hasOwnProperty(/* dependencies */)) {
/* var dependencies = root... */
root.myModule = myModule;
}
}
})(this);
这使依赖项在不同环境中具有通用名称。但是,问题仍然存在:为什么全局对象在闭包的范围内不可用?
编辑 2我一直在尝试使用 RequireJS 和 AMD,并在上面更正了我的代码,以便 AMD 工作。在这种情况下也会发生完全相同的事情:您必须将全局对象显式分配给闭包内的变量,以便它在所述闭包中可用......