JavaScript模块、闭包和作用域
JavaScript Modules, Closures and Scope
我使用以下闭包模式来模块化我的代码:
(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
是可用的,并按照我的期望进行定义。
为什么child.js
中的super
可能来自不同的(即,不是全局的(范围?
我应该补充一点,如果我删除CommonJS导出中的依赖项注入位,它在node.js中会失败,并出现相同的错误(如果有任何依赖项(。
EDIT@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能够工作。在这种情况下也会发生完全相同的事情:你必须将全局对象显式地分配给闭包中的一个变量,它才能在所述闭包中可用。。。
此模式运行良好。如果您实际使用一个名为super
的函数测试它,并通过super()
调用它,您可能会遇到错误,因为super
是一个保留字。以下代码运行良好:
(function(root) {
root.super = function() {
console.log("hello");
};
}) (window);
(function(root) {
root.super();
}) (window);
您可以使用window.super()
调用您的函数。然而CCD_ 21将导致错误。
- 作用域问题-此函数是否形成闭包-JavaScript
- 使用JavaScript回调函数了解变量作用域和闭包
- 具有闭包函数作用域的意外行为
- 作为闭包的回调中的Javascript变量作用域
- javascript中的返回函数,理解作用域&闭包
- JavaScript闭包和作用域问题
- 为什么我的内部内部函数可以访问外部全局作用域变量?这是不是违反了作用域/闭包
- 闭包回调中参数的作用域
- javascript中的闭包只限制变量的作用域吗?
- 将作用域变量传递给在该作用域之外声明的闭包
- 闭包在函数作用域之外不起作用
- 将变量添加到函数作用域/闭包中.函数相当于窗口对象
- 如何程序设置Javascript getter/setter ?(或者实际上是闭包作用域)
- 当使用块作用域变量创建JS闭包时会发生什么?
- 如何在ES2015中解构所有属性到当前作用域/闭包
- 在闭包作用域中设置变量
- 从外部(即定义闭包的作用域)访问闭包内部定义的var
- 显式地将变量作用域设置在函数内而不是闭包内
- 在chrome开发工具中调试带有词法作用域(闭包)的angularjs指令时的奇怪行为
- Javascript作用域/闭包泄漏