为什么这个JavaScript代码(RequireJS和Node.js的模块模式)工作?

由于我对RequireJS和Node.js的理解有限(通常加上JavaScript),我通常会看一些知名的JavaScript库的来源。 每当我看到这样的事情:

( // 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>标记中时自动执行
  • 这个代码可以同时使用RequireJS和Node.js( if在开始的时候检查的if )。 factory函数的结果被分配给module.exports (Node.js),或者用作define函数(RequireJS)的参数。

Q1 :这个代码如何在没有RequireJS和Node.js的情况下工作? ifelse if检查将失败, factory函数永远不会执行,脚本返回nothig。

Q2 :把this作为rootparameter passing的目的是什么? 它从来没有使用过

其实我认为在你的问题剪断的代码将无法使用浏览器全局。 在这个剪辑中使用的模式被称为UMD – 通用模块定义。 实际上这个模式有很多种变化,你可以在https://github.com/umdjs/umd上浏览更多的例&#x5B50;

至于问题:

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); } 

请注意,我们使用传递给wrapper函数的root对象,并且nekman指出它将在浏览器环境中设置为window ,因此我们只是将在该窗口上定义的全局对象传递给工厂,这些对象通常由其他script标记页。 希望这回答你的第二个问题。

Q1:如果ifelse if失败了,唯一假定的是underscoreBackbone从一个<script>标签加载。 前一段时间,我添加了一个提交到Backbone.localStorage插件 ,做了相同的假设。

Q2: this将指向“全局对象”(在浏览器环境中的window ,在Node.js环境中是global )。 在你的情况下,它不被使用,也不需要被传入。仅靠factory就足够了。