JavaScript 模块、闭包和作用域

标签 javascript module scope amd commonjs

我正在使用以下闭包模式来模块化我的代码:

(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.jschild.js具有各自的模块定义,如上所述,其中 super.js创建一个名为 root.super 的函数(在浏览器中为 root === window),如果 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可用并按照我的预期进行定义。

为什么是superchild.js大概来自不同的(即,不是全局)范围?


我应该补充一点,如果我删除 CommonJS 导出中的依赖项注入(inject)位,它会在 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 可以工作。在这种情况下也会发生完全相同的事情:您必须将全局对象显式分配给闭包内的变量,以便它在所述闭包内可用...

最佳答案

这个模式工作得很好。如果您实际使用名为 super 的函数测试它并通过 super() 调用它,您可能会遇到错误,因为 super 是一个reserved word .以下代码工作正常:

(function(root) {

    root.super = function() {

        console.log("hello");

    };

}) (window);

(function(root) {

    root.super();

}) (window);

您可以使用 window.super() 调用您的函数。 super() 但是会导致错误。

关于JavaScript 模块、闭包和作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14381501/

相关文章:

javascript - 问题淡出选择器

javascript - 指示处理器密集型 JS 函数正在运行(GIF 微调器没有动画)

javascript - 如何增强这样的代码

javascript - Controller 内的 Angular $http 函数作用域

.net - Autofac InstancePerMatchingLifetimeScope

javascript - 如何获取括号中可用命令的列表?

perl - 调用子程序的最快方法

android-studio - 构建 gradle 失败但在另一个项目上

linux - 是否可以将 2 个内核模块链接到同一个/dev/device?

javascript - 错误未知提供商 : $scopeProvider <- $scope when using $injector to inject $scope into controller