jQuery 中对 CommonJs 的支持处理

jQuery 中对 CommonJs 提供了直接支持,能够在 CommonJs 模块中直接引用 jQuery 对象,这是如何实现的呢?javascript

从 factory 函数提及

说先看 jQuery 的主体函数定义,这个函数用来返回咱们定义的 jQuery 函数,因此它就是一个工厂函数 factory,在 jQuery 3.0.0 中,就是第 40 行开始,到 10037 行结束。html

#   40   }( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
#10036 return jQuery;
#10037 } ) );

咱们将这个函数抽取出来,简化一下,基本就是下面的样子。java

#   40 function( window, noGlobal ) {

# 90 jQuery = function( selector, context ) {
# 95 };
#10031
if ( !noGlobal ) { #10032 window.jQuery = window.$ = jQuery; #10033 }
#10034
#10035 #10036
return jQuery; #10037 };

 从函数定义能够看到,它须要两个参数,第一个参数就是 window,jQuery 是用来操做 document 的,document 又定义在 window 之上,jQuery 须要经过它来获取 document,以便进行进一步的 DOM 操做。第二个参数则表示是否存在全局对象,若是没有的话,则意味着 jQuery 直接运行在浏览器环境下,不是在 CommonJs 模块环境下,这样的话,就直接将 jQuery 对象挂接到全局的 window 对象上,之后,直接使用 window 来获取 jQuery 对象了。若是在 CommonJs 环境下,就不须要这样作了,由于能够经过 require 来获取 jQuery 对象,就没有必要挂接到 window 对象上了。node

可是,在 #10037 行,咱们并无看到熟悉的直接执行圆括号,那么,何时调用了这个工厂函数呢?jquery

注册函数

咱们回头再来看开头的几行代码。api

# 14 ( function( global, factory ) {
# 15
# 16    "use strict";
# 17
# 18    if ( typeof module === "object" && typeof module.exports === "object" ) {
# 19
# 20        // For CommonJS and CommonJS-like environments where a proper `window`
# 21        // is present, execute the factory and get jQuery.
# 22        // For environments that do not have a `window` with a `document`
# 23        // (such as Node.js), expose a factory as module.exports.
# 24        // This accentuates the need for the creation of a real `window`.
# 25        // e.g. var jQuery = require("jquery")(window);
# 26        // See ticket #14549 for more info.
# 27        module.exports = global.document ?
# 28            factory( global, true ) :
# 29            function( w ) {
# 30                if ( !w.document ) {
# 31                    throw new Error( "jQuery requires a window with a document" );
# 32                }
# 33                return factory( w );
# 34            };
# 35    } else {
# 36        factory( global );
# 37    }
# 38
# 39
// Pass this if window is not defined yet
# 40 }( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

 

这样,这个函数须要一个全局对象,和一个用来建立 jQuery 对象的工厂函数。浏览器

从 #14 到 #40 能够看到这是一个典型的直接执行函数定义,这个函数也须要两个参数,第一个就是咱们所须要的 window 对象,第二个参数就是咱们上面提到的用来建立 jQuery 函数的工厂函数,它已经在前面说过了,因此,咱们先看一下第一个参数。服务器

理论上讲,咱们只须要将浏览器的 window 对象获取到就能够了,可是,还有一种状况是程序运行在 Node.Js 环境下,好比服务器环境下,这时候不是直接运行在浏览器环境下,也就不能直接获取 window 对象了,因此,这里检查了一下,当前是否有 window 对象,没有的化,就将 this 传进来。函数

#40  typeof window !== "undefined" ? window : this

 

在这个函数中须要作什么呢?ui

若是不是在 CommonJs 环境下,很简单了,直接执行工厂函数,让工厂函数将 jQuery 对象注册到 window 对象上,就能够了,这就是 #36 的做用,这里没有传递第二个参数,在 javascript 中,没有提供的参数,值就是 undefined,在用做 boolean 判断的时候,等同于 false。

若是在 CommonJs 环境下,将 jQuery 对象挂接到 module.exports 对象上,就完成任务了。

怎么知道在 CommJs 环境下呢?须要判断一下,#18 就是用来判断当前的运行环境的。

if ( typeof module === "object" && typeof module.exports === "object" ) {

 

CommJs 环境中会有一个 module 对象,这个对象上会有一个 exports 对象。

这样,#27, #28 也比较容易理解了,就是调用 factory 函数来建立出 jQuery 对象,将这个对象注册到 exports 对象上。这里的 noGlobal 参数传递了一个 true,就不会在 window 上再注册 jQuery 对象了。

#27 还有 global.document 是否存在的检查,别忘了,咱们可能运行在非浏览器环境下。

在浏览器环境下,咱们按照上述处理就能够了,若是在非浏览器环境下,就没有当前的 window 对象了,你可能本身建立了一个模拟浏览器的环境,有本身的 window 对象,这个时候的 jQuery 对象须要绑定到你的这个特殊的 window 对象上,#29 - #34 的函数定义了一个工厂函数,你须要将你的 window 对象传递进来,这个工厂函数再调用咱们前面定义的工厂来建立一个绑定到指定 window 的 jQuery 函数供你使用。

相关文章
相关标签/搜索