2013-02-08 76 views
5

由於我對RequireJS和Node.js的理解有限(通常加上JavaScript),我通常會看一些知名JavaScript庫的來源。每次看到這樣的事情:爲什麼這個JavaScript代碼(RequireJS和Node.js的模塊模式)工作?

(// Wrapping 
    function (root, factory) { 
     if (typeof exports === 'object') { // Node.js 

      var underscore = require('underscore'); 
      var backbone = require('backbone'); 

      module.exports = factory(underscore, backbone); 

     } else if (typeof define === 'function' && define.amd) { // Require.JS 

      define(['underscore', 'backbone'], factory); 

     } 
    }(this, function (_, Backbone) { // Factory function, the implementation 
     "option strict"; 

     function Foo() {} 

     return Foo; // Export the constructor 
    }) 
); // Wrapping 

我能理解(希望):

  • 當腳本在<script>標籤uncluded自動執行換行代碼中的匿名函數
  • 此代碼與RequireJS和Node.js(最初的if檢查)一起使用;函數factory的結果被分配給module.exports(Node.js)或用作define函數(RequireJS)的參數。

Q1:此代碼是如何工作沒有RequireJS和Node.js的? ifelse if檢查將失敗,factory函數從不執行並且腳本返回nothig。

Q2:通過this作爲root參數的目的是什麼?這是從來沒有使用

+1

你確定它沒有RequireJS或Node.js嗎?我對JavaScript的理解有限(這可能是錯誤的)[JSFiddle](http://jsfiddle.net/aM3ZT/)讓我覺得你不能訪問Foo() – 2013-02-08 21:17:01

+0

@nekman啊我看到它假定至少有Backbone可用。這是聰明的 – 2013-02-08 21:18:01

+0

@JasonSperske不能確定100%,但看看nekman的答案...... – gremo 2013-02-08 21:22:00

回答

5

其實我認爲在你的問題中剪去的代碼不適用於瀏覽器全局變量。在此剪切中使用的模式稱爲UMD - 通用模塊定義。事實上,有這種模式的很多變化,你可以瀏覽更多的例子在https://github.com/umdjs/umd

至於問題:

Q1 這個片段將不會在瀏覽器中沒有RequireJS或任何其他AMD裝載機工作,爲顯而易見的原因 - 只有兩次檢查 - 對於NodeJS和定義函數,所以不使用AMD庫時不會調用工廠函數。

爲了使所謂的添加另一條件瀏覽器全局

if (typeof exports === 'object') { // Node.js 
    var underscore = require('underscore'); 
    var backbone = require('backbone'); 
    module.exports = factory(underscore, backbone); 

} else if (typeof define === 'function' && define.amd) { // Require.JS 
    define(['underscore', 'backbone'], factory); 
} else { 
    // Browser globals 
    factory(root._, root.Backbone); 
} 

請注意,我們使用傳遞到包裝函數根對象和nekman指出它將被設置爲在瀏覽器環境window出廠功能,所以我們只是將在該窗口中定義的全局對象傳遞給工廠,這些對象通常由頁面上的其他script標籤定義。希望這回答你的第二個問題。

+0

+1,感謝UMD鏈接!正如我所說我正在學習JavaScript,而我不明白的是如何在不使用Node.js或Require.JS時訪問'Foo'構造函數。唯一的方法是編寫'root.Foo = factory(root._,root.Backbone)',對吧? – gremo 2013-02-08 22:35:45

+0

其實我在這裏找到了我評論的答案:https://github.com/umdjs/umd/blob/master/returnExports.js – gremo 2013-02-08 22:39:56

+0

是的,這是做到這一點的方法,你只需返回你的對象(' Foo'),如果我們在瀏覽器中,我們應該將它添加到'root'(這是窗口),以便其他模塊可以看到它。 – 2013-02-08 22:41:18

2

Q1:如果同時ifelse if失敗,承擔的唯一的事情就是underscoreBackbone<script>標籤加載。一段時間前,我做了added a commitBackbone.localStorage plugin做了相同的假設。

Q2:this將指向「全局對象」(window在瀏覽器環境和global在Node.js的環境)。在你的情況下,它不會被使用,也不需要傳入。單獨使用factory就足夠了。

+1

對於** Q1 **:我無法理解當if和else if失敗時正在執行的行即瀏覽器)。你能解釋一下嗎?我如何訪問'Foo()'? – gremo 2013-02-08 21:20:42

+1

是的,這是正確啓動!如果兩者都失敗了,那麼應該有一個:else {factory(_,Backbone); }'訪問工廠和'Foo'。 – nekman 2013-02-08 21:28:32

+0

即使有'return factory(_,Backbone)'我也搞不明白,在包含'

  • 11. 爲什麼這個代碼不工作?
  • 12. 爲什麼這個代碼不工作
  • 13. 的JavaScript模塊模式,這
  • 14. 爲什麼這個javascript對象的行爲與模塊模式不一樣?
  • 15. 爲什麼這個特定的JavaScript代碼以這種方式工作?
  • 16. 爲什麼不是這個簡單的JavaScript代碼工作?
  • 17. 請解釋爲什麼這個奇怪的javascript代碼工作
  • 18. Node.js - 爲什麼這些模塊不能像我期望的那樣工作?
  • 19. 爲什麼這個代碼中的模式沒有詳盡?
  • 20. 爲什麼Node.js中沒有這個代碼塊?
  • 21. 這對JavaScript模塊模式
  • 22. Javascript模塊模式,範圍和「這」
  • 23. 爲什麼這個JavaScript代碼不工作?
  • 24. 爲什麼這個JavaScript代碼不能按預期工作?
  • 25. 爲什麼這個JavaScript Cookie代碼不工作?
  • 26. 這兩個requirejs模塊有什麼區別?
  • 27. node.js模塊的特定代碼塊
  • 28. Node.js的Cluster模塊和Learnboost的Cluster模塊有什麼區別?
  • 29. 這個模板代碼爲什麼不起作用?
  • 30. 在node.js模塊上工作