jQuery源碼-jQuery.extend


從jQuery的源碼中可以看到,jQuery.extend和jQuery.fn.extend其實是同指向同一方法的不同引用

jQuery.extend = jQuery.fn.extend = function() {

瞄了下它的代碼,其實不復雜,但是在jQuery中扮演了極其重要的作用

jQuery.extend 對jQuery本身的屬性和方法進行了擴展

jQuery.fn.extend 對jQuery.fn的屬性和方法進行了擴展

// 擴展jQuery對象本身,此處添加了jQuery.noConflict方法
jQuery.extend({
    noConflict: function(deep){
        //實現細節略
    },
    //..
})

// 擴展jQuery.fn,此處添加 jQuery.fn.data方法
jQuery.fn.extend({
    data: function( key, value ) {
        //實現細節略
    },
    //...
})

 

extend的各種用法

下面會舉例說明extend的常見使用方法,最后面的時候簡單提下extend方法內部一些實現細節

實例一:擴展jQuery本身

代碼如下

jQuery.extend({nick: 'casper'});

打印下

console.log(jQuery.nick);   //輸出:'casper'

 

實例二:擴展對象

代碼如下,將obj2的的屬性/方法拷貝到obj1上,需要注意的有兩點

  1. obj1本身會被修改
  2. 返回的事修改后的obj1
var obj1 = {nick: 'casper'},
    obj2 = {nick: 'chyingp', age: 25};
var obj3 = jQuery.extend(obj1, obj2);

打印下

console.log( JSON.stringify(obj1) );    // 輸出 {"nick":"chyingp","age":25}
console.log( JSON.stringify(obj3) );    // 輸出 {"nick":"chyingp","age":25}

 

實例三:淺拷貝-當obj中存在引用

如下代碼,obj1.scores 的值是個指向對象的引用,當obj2中存在同名應用時,默認obj2中的同名引用會覆蓋obj1中那個

var obj1 = { nick: 'casper',  scores: { math: 100, English: 100 } },
    obj2 = { scores: { hitory: 100 } },
    obj3 = jQuery.extend(obj1, obj2);

打印下

console.log( JSON.stringify(obj1) );    // 輸出 {"nick":"casper","scores":{"hitory":100}}

 

實例四:深拷貝-當obj中存在引用

還是實例三的代碼,不同的是,第一個參數改成true,表明這是深拷貝

var obj1 = { nick: 'casper',  scores: { math: 100, English: 100 } },
    obj2 = { scores: { hitory: 100 } },
    obj3 = jQuery.extend( true, obj1, obj2 );

打印下

console.log( JSON.stringify(obj1) );    // 輸出 {"nick":"casper","scores":{"math":100,"English":100,"hitory":100}}

 

實例五:擴展jQuery.fn

如下代碼,給jQuery.fn添加 say 方法~

jQuery.fn.extend({
    say: function(){
        console.log("hello, I'm "+this.attr('id'));
    }
});

打印下

$('#casper').say(); // 輸出 hello, I'm casper

 

extend的實現細節

直接上代碼

jQuery.extend = jQuery.fn.extend = function() {
    var src, copyIsArray, copy, name, options, clone,
        target = arguments[0] || {},    // 常見用法 jQuery.extend( obj1, obj2 ),此時,target為arguments[0]
        i = 1,
        length = arguments.length,
        deep = false;

    // Handle a deep copy situation
    if ( typeof target === "boolean" ) {    // 如果第一個參數為true,即 jQuery.extend( true, obj1, obj2 ); 的情況
        deep = target;  // 此時target是true
        target = arguments[1] || {};    // target改為 obj1
        // skip the boolean and the target
        i = 2;
    }

    // Handle case when target is a string or something (possible in deep copy)
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {  // 處理奇怪的情況,比如 jQuery.extend( 'hello' , {nick: 'casper})~~
        target = {};
    }

    // extend jQuery itself if only one argument is passed
    if ( length === i ) {   // 處理這種情況 jQuery.extend(obj),或 jQuery.fn.extend( obj )
        target = this;  // jQuery.extend時,this指的是jQuery;jQuery.fn.extend時,this指的是jQuery.fn
        --i;
    }

    for ( ; i < length; i++ ) {
        // Only deal with non-null/undefined values
        if ( (options = arguments[ i ]) != null ) { // 比如 jQuery.extend( obj1, obj2, obj3, ojb4 ),options則為 obj2、obj3...
            // Extend the base object
            for ( name in options ) {
                src = target[ name ];
                copy = options[ name ];

                // Prevent never-ending loop
                if ( target === copy ) {    // 防止自引用,不贅述
                    continue;
                }

                // Recurse if we're merging plain objects or arrays
                // 如果是深拷貝,且被拷貝的屬性值本身是個對象
                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                    if ( copyIsArray ) {    // 被拷貝的屬性值是個數組
                        copyIsArray = false;
                        clone = src && jQuery.isArray(src) ? src : [];

                    } else {    被拷貝的屬性值是個plainObject,比如{ nick: 'casper' }
                        clone = src && jQuery.isPlainObject(src) ? src : {};
                    }

                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );  // 遞歸~

                // Don't bring in undefined values
                } else if ( copy !== undefined ) {  // 淺拷貝,且屬性值不為undefined
                    target[ name ] = copy;
                }
            }
        }
    }

    // Return the modified object
    return target;
};

 

結束語

jQuery.extend / jQuery.fn.extend方法本身很簡單,但在jQuery整體設計中的作用非常重要,理解了jQuery.extend(obj)、jQuery.fn.extend(obj) 分別是對jQuery本身、jQuery.fn 進行擴展,對后續的源碼分析會很有幫助,除此之外,沒了~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM