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 函數供你使用。

相關文章
相關標籤/搜索