$.extend中探索深拷貝和淺拷貝
阿新 • • 發佈:2018-12-30
網上這方面的教程比較多,由於上次看了篇錯誤的教程搞得我迷糊;特意寫下這篇筆記,若文中有錯誤之處,忘路過的朋友及時指出,不想禍害其他朋友了;
首先說明下:深拷貝(深複製)和淺拷貝(淺複製),特地說明怕有人以為又是不同的概念,其實是一樣的;
1.淺拷貝(淺複製):一句話概況就是多個物件之間對Objectl型別資料的備份,其實只是備份儲存在棧記憶體中的地址;本質上還是指向同一個堆記憶體中的資料;
例項程式碼如下:
以上程式碼可知:當你改變obj物件的name屬性,通過淺拷貝過去的obj1物件的name屬性也會相應的改變;這種結果在跟後臺做互動的時候會很出現各種各樣的毛病;
2.深拷貝(深複製):深拷貝不再侷限於對於物件記憶體地址的引用了,它是完全複製了一個物件,把被複制的物件的遍歷一遍,然後賦值給新的物件並返回;
3.在jQuery框架中的$.extend()方法就是這麼實現的;不過jQuery的深拷貝還分為兩部分:普通深拷貝和遞迴(深度)深拷貝(我亂起的名字,不喜勿噴);我們就根據$.extend()方法來分析深拷貝;
先貼上jQuery原始碼:(只有$.extend方法的那一段)=>$.extend(boolean,obj1,obj2);
jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, //獲取第一個引數並賦給變數target i = 1, length = arguments.length, //獲取引數的長度 deep = false; //deep變數決定是否進行普通拷貝還是遞迴拷貝 // Handle a deep copy situation if ( typeof target === "boolean" ) { //判斷變數target是否是boolean型別 deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } //如果函式引數只有一個,那麼target變數則引用jQuery例項化的物件; if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) {//遍歷所傳參 if ( ( options = arguments[ i ] ) != null ) {//並將引數復值給變數options for ( name in options ) { src = target[ name ]; copy = options[ name ]; //判斷目標物件和需要被複制的物件是否一致,一致就跳過進行下一次迴圈 //目標物件target;被複制的物件copy if ( target === copy ) { continue; } // 如果deep是true,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 : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; };
從上面原始碼分析可知,jQuery中的extend()方法不過deep是否是true還是false,它都是進行深拷貝(深複製)的;同時extend方法進行深拷貝的條件還有需要被拷貝的物件,也就是extend()方法中的copy變數是否是物件還是陣列;如果copy物件不是一個引用型別(物件或陣列),比如字串:則仍會將字串作為類陣列被for in進行迴圈並分解給目標物件target;並且不管是普通深拷貝還是遞迴深拷貝,最終返回的是被處理過的目標物件target;
程式碼如下: