jQuery 學習筆記:jQuery 代碼結構

jQuery 學習筆記:jQuery 代碼結構

這是我學習 jQuery 過程當中整理的筆記,這一部分主要包括 jQuery 的代碼最外層的結構,寫出來整理本身的學習成果,有錯誤歡迎指出。javascript

jQuery 的最外層 $,jQuery

(function (global, factory) {
    "use strict";
    if (typeof module === "object" && typeof module.exports === "object") { // 判斷是否使用 commonjs 環境
        module.exports = global.document ?
            factory(global, true) :
            function (w) {
                if (!w.document) {
                    throw new Error("jQuery requires a window with a document");
                }
                return factory(w);
            };
    } else {
        factory(global);
    }
})(typeof window !== "undefined" ? window : this,  function (window, noGlobal){
    if (typeof define === "function" && define.amd) {  // 是否使用 AMD 模塊化規範
        define("jquery", [], function () {
            return jQuery;
        });
    }
    var
        _jQuery = window.jQuery,
        _$ = window.$;
    jQuery.noConflict = function (deep) {
        if (window.$ === jQuery) {
            window.$ = _$;
        }
        if (deep && window.jQuery === jQuery) {
            window.jQuery = _jQuery;
        }
        return jQuery;
    };
    if (!noGlobal) {
        window.jQuery = window.$ = jQuery;
    }
    return jQuery;
});

上面是 jQuery-3.3.1 的一部分代碼,是最外層的一部分,包含了大量的信息。css

(function (global, factory) {
})(typeof window !== "undefined" ? window : this, function (window, noGlobal){
});

jQuery 代碼包含在一個自執行的函數內,而後返回出一個指向 jQuery 的索引,就造成了一個閉包,利用 jQuery 對象,能夠訪問定義在自執行函數內的方法,在外面則訪問不到,防止變量命名同外界產生衝突,同時,window 對象做爲參數傳入函數,在函數內,將 jQuery 和 $ 掛載到 window 對象對象上,這樣,在外界也能夠直接經過 window.$ 和 window.jQuery 訪問到 jQuery 對象。一般使用較多的 $,實際指的就是 window.$,但一般會省略掉 window 對象。html

if (!noGlobal) {
        window.jQuery = window.$ = jQuery; // 將 jQuery 和 $ 掛載到 window 對象對象上
    }
    return jQuery; // 而後返回出一個指向 jQuery 的索引

同時,爲了防止不一樣庫對 $ 的指向產生衝突,jQuery 還能夠將 $ 和 jQuery 還原成原來的指向,只要使用 jQuery.noConflict 方法。java

var
        _jQuery = window.jQuery, // 保存 window.jQuery 的值
        _$ = window.$; // 保存 window.$ 的值
    jQuery.noConflict = function (deep) {
        if (window.$ === jQuery) {
            window.$ = _$;
        }
        if (deep && window.jQuery === jQuery) { // 根據參數判斷是否還原 window.jQuery 的值
            window.jQuery = _jQuery;
        }
        return jQuery;
    };

先使用 _jQuery 和 _$ 保存 window.jQuery 和 window.$ 的原始值,若是調用 jQuery.noConflict 方法,判斷傳入的參數,若是參數值爲 false,就僅釋放 $,還原爲原來的值,若是參數值爲 true,就將 window.jQuery 也還原爲原來的值。node

jQuery 函數的重載

jQuery 在使用時,既能夠做爲一個函數,直接調用 $,傳入參數,也能夠將其做爲對象,調用對象的方法,做爲對象的狀況以後再討論,先說將 $ 做爲函數使用。jquery

因爲 jQuery 中同名函數會覆蓋,傳入參數不一樣時,不能從多個同名函數中選擇某個函數,並且根據函數名選擇惟一的函數,因此當傳入參數種類不一樣時,就須要根據參數的個數,類型等信息判斷具體的處理方式了。當調用 jQuery 時,指向的是一個函數。閉包

jQuery = function (selector, context) {
    return new jQuery.fn.init(selector, context);
},

會直接返回一個以 jQuery.fn.init 爲構造函數,new 出的對象。而在 jQuery.fn.init 函數中,則會根據傳入的參數的不一樣,進行不一樣的處理。架構

init = jQuery.fn.init = function (selector, context, root) {
        var match, elem;
        if (!selector) { // 若是第一個參數爲空,直接 return 調用函數的對象
          return this;
        }
        root = root || rootjQuery;
        if (typeof selector === "string") {
            // 參數爲字符串,進行處理
        } else if (selector.nodeType) {
            // 參數爲元素節點,進行處理
        } else if (isFunction(selector)) {
            //參數爲函數,進行處理
        }
        return jQuery.makeArray(selector, this);
      };
    init.prototype = jQuery.fn; // 將 init 函數的原型指定爲 jQuery.fn,則 init 構造函數 new 出的對象就均可以直接使用 init 函數的原型也就是 jQuery.fn 包含的方法。

當參數爲空時,返回 init 函數的調用者,最終,會返回 jQuery,即 $ 對象,可使用對象上的方法。當第一個參數爲字符串時,能夠是選擇器,html代碼(會建立DOM元素幷包裝成 jQuery 對象),當爲 DOM 對象時,包裝成 jQuery 對象,當爲函數時,$(fn) 至關於 $(document).ready(fn),會在頁面頁面 DOM 加載完成後調用 fn,性能上優於 window.onload。模塊化

jQuery 插件

上面說到,jQuery 能夠做爲一個對象,使用其綁定的方法,例如 $.trim 方法,能夠去除字符串兩邊的空格。此外,jQuery 對象的構造函數 init 的原型指向 jQuery.fn,則 DOM 對象被包裝成 jQuery 對象後,就能夠調用 jQuery.fn 的方法了,例如 $('p').css 方法等。這兩種方法均可以添加新的方法,對應了 jQuery 的兩種插件。函數

添加插件使用的是 jQuery.extend 函數,以及 jQuery.fn.extend,其實指向的是同一個函數,只是函數的調用者不一樣,this 指向就不一樣了。

$.extend 函數自己能夠做爲一個工具函數,處理對象的合併,語法 jQuery.extend([deep], target, object1, [objectN]),這個函數會判斷第一個參數是不是一個 Boolean 值(可選),若是是,則進行深拷貝,若是不是,則進行淺拷貝。而後根據除了 Boolean 值以外的其餘參數的個數,判斷是不是添加插件,若是剩餘參數不止一個,則第一個做爲 target,其餘對象的屬性將會複製到 target 上,而若是隻有一個參數,則會將這個參數對象的方法添加到 jQuery 對象上,或者 jQuery.fn 上,根據調用函數的對象不一樣決定。例如:

:(function($) {
    $.fn.extend({ // 參數對象
        'color': function(){ // 對象的屬性將會複製到 $.fn 上
            // 插件代碼
        },
        'border': function () {
            // 插件代碼
        }
    });
})(jQuery);

jQuery 自己的代碼中,也大量使用了 $.extend 方法。這個方法能夠和 Object.assign() 對照學習。

資料:

相關文章
相關標籤/搜索