JavaScript模块,闭包和范围 [英] JavaScript Modules, Closures and Scope
问题描述
我正在使用以下关闭模式来模块化我的代码:
I am using the following closure pattern to modularise my code:
(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或基本的全局名称空间实例化.
i.e., We use feature detection to support CommonJS modules (e.g., node.js), AMD or basic global namespace instantiation.
这在node.js中工作正常; 我还没有测试过AMD模式,因为我还在阅读中(请参见AMD表现出完全相同的效果);但是在浏览器 if 中失败,该模块具有任何依赖关系.就是说,如果myModule
引用了在另一个模块中定义的内容:例如,假设我有带有各自模块定义的super.js
和child.js
,如上所述,其中super.js
创建了一个名为<的函数. c4>(在浏览器中为root === window
),如果child.js
尝试执行super()
,我将得到类似super is not a function
的内容.
This works fine in node.js; I haven't tested the AMD pattern yet, as I'm still reading up on it (See Edit 2: AMD exhibits the exact same effect); but it fails in the browser if the module has any dependencies. That is, say, if myModule
references something that is defined in a different module: For example, say if I had super.js
and child.js
with respective module definitions, as above, where super.js
creates a function called root.super
(root === window
in the browser), if child.js
tries to do super()
, I will get something like super is not a function
.
这是怎么回事?
为解决此问题,我更改了<script>
元素中super.js
和child.js
的加载顺序:祝您好运.然后我尝试使用jQuery强制child.js
在文档准备好时加载:
To try to fix it, I changed the order in which super.js
and child.js
are loaded in <script>
elements: No luck. Then I tried forcing child.js
to load when the document is ready, using jQuery:
$(document).ready(function() {
$.getScript('child.js', function() {
// Do stuff with child, which calls super
});
});
...同样,同样的问题.但是,在两种情况下,如果我都进入控制台,则super
可用并已按照我的期望进行定义.
...again, same problem. However, in both cases, if I enter the console, super
is available and defined as I'm expecting.
为什么super
在child.js
中可能来自不同的范围(即不是全局范围)?
Why is super
in child.js
presumably from a different (i.e., not the global) scope?
如果我删除CommonJS导出中的依赖项注入位,我应该添加,它在node.js中失败,并出现相同的错误(如果有任何依赖项).
I should add, if I remove the dependency injection bit in the CommonJS export, it fails in node.js with the same error (if there are any dependants).
编辑 @Amberlamps的答案解决了该问题,但未回答有关为什么会发生的问题.我的模块模式现在是:
EDIT @Amberlamps' answer solved the problem, but it didn't answer the question as to why this occurs. My module pattern is now:
(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);
这在整个环境中使受抚养人拥有一个通用名称.但是,问题仍然存在:为什么全局对象在闭包的范围内不可用?
This keeps dependants with a common name, across environments. However, the question remains: Why is the global object not available within the closure's scope?
编辑2 我一直在尝试RequireJS和AMD,并更正了上面的代码,以便AMD可以正常工作.在这种情况下,也确实发生了同样的事情:您必须将全局对象显式分配给闭包中的变量,以使其在所述闭包中可用...
EDIT 2 I've been experimenting with RequireJS and AMD and have corrected my code, above, so that the AMDs work. Exactly the same thing happens in this case, too: You have to explicitly assign the global object to a variable within the closure for it to be available within said closure...
推荐答案
此模式很好用.如果您实际上使用名为super
的功能对其进行了测试并通过super()
进行了调用,则可能会遇到错误,因为super
是
This pattern works just fine. If you actually tested it with a function called super
and calling it via super()
, you might ran into an error, because super
is a reserved word. Following code works fine:
(function(root) {
root.super = function() {
console.log("hello");
};
}) (window);
(function(root) {
root.super();
}) (window);
您可以使用window.super()
调用函数. super()
但是会导致错误.
You can call your function using window.super()
. super()
however will result in an error.
这篇关于JavaScript模块,闭包和范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!