2013-01-17 110 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