我使用下面的封閉模式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.js
和child.js
帶有各自的模塊定義,如上所述,其中super.js
創建了一個名爲root.super
(root === window
在瀏覽器中)的函數,if child.js
試圖做super()
,我會得到類似super is not a function
的東西。
這是怎麼回事嗎?
要嘗試修復它,我更改了super.js
和child.js
加載的順序<script>
元素:沒有運氣。然後我試圖迫使child.js
使用jQuery當文檔準備好加載,:
$(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);
這使得在不同環境中使用通用名稱的依賴項。然而,問題依然存在:爲什麼全局對象在閉包的範圍內不可用?
EDIT 2我一直在嘗試與RequireJS和AMD並已經改正了我的代碼,上面,從而使AMD的工作。在這種情況下也會發生完全相同的事情:您必須明確地將全局對象分配給閉包內的變量,以便在閉包中可用。
這是'window'對象嗎? – Amberlamps
@Amberlamps,我假設你正在談論'this'是否是'root'的別名。在瀏覽器中'this'指的是'window',但在服務器上(node.js)'this'指的是'global'。使用「root」別名允許在客戶端和服務器端使用模塊。 – zzzzBov
@zzzzBov:我知道,但如果IIFE不在全球範圍內,這可能是任何事情。 – Amberlamps