JavaScript模块,闭包和范围 [英] JavaScript Modules, Closures and Scope

查看:99
本文介绍了JavaScript模块,闭包和范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.jschild.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.jschild.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.

为什么superchild.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆