为什么这个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的情况下工作? if
和else if
检查将失败, factory
函数永远不会执行,脚本返回nothig。
Q2 :把this
作为root
parameter passing的目的是什么? 它从来没有使用过
其实我认为在你的问题剪断的代码将无法使用浏览器全局。 在这个剪辑中使用的模式被称为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); }
请注意,我们使用传递给wrapper函数的root对象,并且nekman指出它将在浏览器环境中设置为window
,因此我们只是将在该窗口上定义的全局对象传递给工厂,这些对象通常由其他script
标记页。 希望这回答你的第二个问题。
Q1:如果if
和else if
失败了,唯一假定的是underscore
和Backbone
从一个<script>
标签加载。 前一段时间,我添加了一个提交到Backbone.localStorage插件 ,做了相同的假设。
Q2: this
将指向“全局对象”(在浏览器环境中的window
,在Node.js环境中是global
)。 在你的情况下,它不被使用,也不需要被传入。仅靠factory
就足够了。