JavaScript模块,闭包和范围

时间:2013-01-17 14:41:03

标签: 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 1}}在浏览器中创建一个名为root.superroot === window)的函数,如果child.js尝试执行super(),我会得到类似super is not a function的内容。< / p>

这里发生了什么?

要尝试修复它,我更改了super.jschild.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);

这使得dependents在不同环境中具有通用名称。但问题仍然存在:为什么全局对象在闭包范围内不可用?


编辑2 我一直在尝试使用RequireJS和AMD,并修正了上面的代码,以便AMD运行。在这种情况下也会发生完全相同的事情:您必须将全局对象显式地分配给闭包内的变量,以便在所述闭包内可用...

1 个答案:

答案 0 :(得分:2)

这种模式很好用。如果您使用名为super的函数对其进行了实际测试并通过super()调用它,则可能会遇到错误,因为superreserved word。以下代码工作正常:

(function(root) {

    root.super = function() {

        console.log("hello");

    };

}) (window);

(function(root) {

    root.super();

}) (window);

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