1. 程式人生 > >$.extend中探索深拷貝和淺拷貝

$.extend中探索深拷貝和淺拷貝

網上這方面的教程比較多,由於上次看了篇錯誤的教程搞得我迷糊;特意寫下這篇筆記,若文中有錯誤之處,忘路過的朋友及時指出,不想禍害其他朋友了;

首先說明下:深拷貝(深複製)和淺拷貝(淺複製),特地說明怕有人以為又是不同的概念,其實是一樣的;

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;

程式碼如下: