我使用下面的封闭模式modularise我的代码:的JavaScript模块,关闭和范围
(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
在浏览器中)的函数,if child.js
试图做super()
,我会得到类似super is not a function
的东西。
这是怎么回事吗?
要尝试修复它,我更改了super.js
和child.js
加载的顺序<script>
元素:没有运气。然后我试图迫使child.js
使用jQuery当文档准备好加载,:
$(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);
这使得在不同环境中使用通用名称的依赖项。然而,问题依然存在:为什么全局对象在闭包的范围内不可用?
EDIT 2我一直在尝试与RequireJS和AMD并已经改正了我的代码,上面,从而使AMD的工作。在这种情况下也会发生完全相同的事情:您必须明确地将全局对象分配给闭包内的变量,以便在闭包中可用。
这是'window'对象吗? – Amberlamps
@Amberlamps,我假设你正在谈论'this'是否是'root'的别名。在浏览器中'this'指的是'window',但在服务器上(node.js)'this'指的是'global'。使用“root”别名允许在客户端和服务器端使用模块。 – zzzzBov
@zzzzBov:我知道,但如果IIFE不在全球范围内,这可能是任何事情。 – Amberlamps