JavaScript模块,闭包和作用域

4

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

(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中运行良好;但如果模块有任何依赖项,则在浏览器中失败。也就是说,假设myModule引用了在不同模块中定义的内容:例如,假设我有super.js和child.js,具有相应的模块定义,如上所述,其中super.js创建一个名为root.super的函数(在浏览器中,root === window),如果child.js尝试执行super(),我将得到类似“super is not a function”的错误消息。
这是怎么回事呢?
为了尝试解决它,我更改了在

1
@Amberlamps,我猜你说的是this被别名为root的情况。在浏览器中,this指的是window,但在服务器(node.js)中,this指的是global。使用root的别名可以使模块在客户端和服务器端都能够使用。 - zzzzBov
@zzzzBov:我知道,但是如果IIFE不在全局范围内,this可以是任何东西。 - Amberlamps
@topic 我无法理解你的问题,因为我没有看到任何错误。 - Amberlamps
@zzzzBov:我只是在尝试解决问题。你永远不会知道... - Amberlamps
你为什么那么确定在AMD加载器中“this/root”会得到实际的“window”引用?在AMD规范中绝对没有这样的保证。整个模块可以被包装到另一个闭包中,其中“global”实际上是一个本地合成对象并进行了评估。如果你需要“window”,就按名称请求它。顺便说一下,这种方式深入编辑后问题变得不清楚。你能给出实际的源代码说明哪里出了问题吗? - ddotsenko
显示剩余2条评论
1个回答

2

这个模式可以正常工作。如果你用一个叫做super的函数进行测试,并通过super()来调用它,可能会遇到错误,因为super是一个保留字。以下代码可以正常工作:

(function(root) {

    root.super = function() {

        console.log("hello");

    };

}) (window);

(function(root) {

    root.super();

}) (window);

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

superchild是我想到的第一个语义示例,实际上我使用了不同的名称... 不管怎样,谢谢您 :) 但是,为什么会这样呢?为什么全局名称在闭包作用域中不可用? - Xophmeister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接