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

目錄javascript

1 . jquery extend的基本使用

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

<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的拷貝分深拷貝和淺拷貝。jquery

<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個部分:json

定義了一些變量數組

if(){}  是否是深拷貝this

if(){}  參數正確不spa

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

for   傳入多個對象的狀況code

      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;
                }
            }
        }
    }
相關文章
相關標籤/搜索