1. 程式人生 > >jquery的2.0.3版本源碼系列(3):285-348行,extend方法詳解

jquery的2.0.3版本源碼系列(3):285-348行,extend方法詳解

ffffff 相同 語法 mic 處理 說明 json對象 關註 深拷貝

目錄

1 . jquery extend的基本使用

通過285行的源碼 jQuery.extend = jQuery.fn.extend = function() { ,extend方法要麽是直接掛在到jQuery的靜態方法,要麽是掛載到fn上其實就是原型上(參考283行的賦值操作)的實例方法。extend方法可以傳一個對象,類似於插件的方式,也可以傳多個對象進行拷貝。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        $.extend({
            aaa:function
(){ alert("1"); }, bbb:function(){ alert("2"); } }) $.fn.extend({ aaa:function(){ alert("3"); }, bbb:function(){ alert("4"); } }) $.aaa();
//彈出1,靜態方法可以直接調用 $().aaa();//彈出3,綁定到fn上的方法,以對象的形式調用 //多個對象參數,後面的對象會擴展到第一個對象上 var a={}; $.extend(a,{color:‘#f40‘}); console.log(a);//color所在的對象就被擴展到a對象上 </script>

接下來關註extend的拷貝分深拷貝和淺拷貝。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        var
a={}; var b={name:"hello"}; var c={name:"hello-1"}; var d={name:{age:20}}; var e={name:{age:50}}; //淺拷貝對象b $.extend(a,b); a.name="hi"; alert(b.name);//彈出hello //淺拷貝對象d $.extend(a,d); a.name.age=30; alert(d.name.age);//彈出30 //深拷貝對象c $.extend(true,a,c); a.name="hi"; alert(c.name);//彈出hello-1 //深拷貝對象e $.extend(true,a,e); a.name.age=40; alert(e.name.age);//彈出50 </script>

2.代碼簡化版本

分為5個部分:

定義了一些變量

if(){} 是不是深拷貝

if(){} 參數正確不

if(){} 看是不是插件的情況,插件的話傳入一個含有方法的json對象

for 傳入多個對象的情況

if防止循環應用,if深拷貝,else if淺拷貝。

詳解篇:3.1 定義了一些變量

var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

這裏要說明一下target。它就是 $.extend(a,d); 拷貝的目標對象a。這裏的arguments是javascript的內置對象,是一個類數組,索引為0的值當然是參數a。

詳解篇:3.2 看是不是深拷貝

// 處理深拷貝的情形
    if ( typeof target === "boolean" ) {
        deep = target;
        target = arguments[1] || {};
        // 如果傳入的第一個參數為true,那麽deep就置為true了。target目標對象就調整為第二個。
       //跳過布爾值和target
        i = 2;
    }

這裏處理的是傳入了true的情況,比如 $.extend(true,a,c);

詳解篇:3.3 要傳正確的的參數

// 如果傳進來的並非object同時也不是function,那麽target置為空對象。
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
        target = {};
    }

詳解篇:3.4 處理插件的情形

// 如果傳進來一個參數,那麽target目標對象就為jquery自己。
    if ( length === i ) {
        target = this;
        --i;
    }

詳解篇:3.5 傳入多個對象的操作

基本思路是通過arguments進行取值,獲取到每個非目標對象的參數。非target對象通過in循環,獲取到屬性名。

總體特征是淺拷貝只能拷貝一層,深拷貝可以連嵌套子對象也能拷貝進去。

淺拷貝的情況下,那麽走的是else分支,對相應的值進行覆蓋 target[ name ] = copy; 。可以看到如果原來有target有相同的屬性,那麽就覆蓋,如果沒有,那麽就添加上。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        var a={name:{age:20}};
        var b={name:{age:50}};
        //淺拷貝對象b
        $.extend(false,a,b);
        console.log(a);//{name:{age:20}}
        console.log(b);//{name:{age:50}}
    </script>

它遇到對象嵌套,copy這裏是{age:50},通過簡單的賦值是修改不了的。

<script>
        var a={name:{age:20}};
        var b={name:{age:50}};
        a[name]=b[name];
        console.log(a);//{name:{age:20}},沒有變化哦。
    </script>

深拷貝的情況下。copy是數組,src也為數組賦值給clone否則為空數組。copy是對象,src是對象賦值給clone否則為空對象。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        var a={name:{age:20}};
        var b={name:{age:50}};
        //淺拷貝對象b
        $.extend(true,a,b);
        console.log(a);//{name:{age:50}}
        console.log(b);//{name:{age:50}}
    </script>

深拷貝的copy等於{age:50},src等於{age:20}。那麽通過克隆的方式就可以把copy給到src。這其實是一個遞歸調用,所以深拷貝會拷貝到底。

for ( ; i < length; i++ ) {
        // 處理非空或者沒有定義的情況
        if ( (options = arguments[ i ]) != null ) {
            // 擴展基礎對象,in語法把屬性值取出來
            for ( name in options ) {
                src = target[ name ];
                copy = options[ name ];

                // 防止無限循環,類似$.extend(a,{name:a})。那麽如果拷貝的某一個值就等於target那麽就終止代碼在繼續循環
                if ( target === copy ) {
                    continue;
                }

                // 深拷貝和copy存在,以及copy要麽是對象、要麽是數組
                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                    if ( copyIsArray ) {
                        copyIsArray = false;
                        clone = src && jQuery.isArray(src) ? src : [];

                    } else {
                        clone = src && jQuery.isPlainObject(src) ? src : {};
                    }

                    // 不移動原對象,克隆他們。
                    target[ name ] = jQuery.extend( deep, clone, copy );

                // Don‘t bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }

jquery的2.0.3版本源碼系列(3):285-348行,extend方法詳解