2013-01-17 77 views
4

我使用下面的封闭模式modularise我的代码:的JavaScript模块,关闭和范围

(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.superroot === window在浏览器中)的函数,if child.js试图做super(),我会得到类似super is not a function的东西。

这是怎么回事吗?

要尝试修复它,我更改了super.jschild.js加载的顺序<script>元素:没有运气。然后我试图迫使child.js使用jQuery当文档准备好加载,:

$(document).ready(function() { 
    $.getScript('child.js', function() { 
    // Do stuff with child, which calls super 
    }); 
}); 

...再次,同样的问题。但是,在这两种情况下,如果我进入控制台,则可以使用super并按照我的预期进行定义。

为什么superchild.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); 

这使得在不同环境中使用通用名称的依赖项。然而,问题依然存在:为什么全局对象在闭包的范围内不可用?


EDIT 2我一直在尝试与RequireJS和AMD并已经改正了我的代码,上面,从而使AMD的工作。在这种情况下也会发生完全相同的事情:您必须明确地将全局对象分配给闭包内的变量,以便在闭包中可用。

+0

这是'window'对象吗? – Amberlamps

+1

@Amberlamps,我假设你正在谈论'this'是否是'root'的别名。在浏览器中'this'指的是'window',但在服务器上(node.js)'this'指的是'global'。使用“root”别名允许在客户端和服务器端使用模块。 – zzzzBov

+0

@zzzzBov:我知道,但如果IIFE不在全球范围内,这可能是任何事情。 – Amberlamps

回答

2

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

(function(root) { 

    root.super = function() { 

     console.log("hello"); 

    }; 

}) (window); 

(function(root) { 

    root.super(); 

}) (window); 

可以使用window.super()调用你的函数。然而,super()会导致错误。

+0

'super'和'child'是我提出的第一个语义示例,我实际上使用了不同的名字......无论如何,感谢你的这个:)但是,为什么会这样呢?为什么全局名称在闭包的范围内不可用? – Xophmeister