1. 程式人生 > >談談淺拷貝和深拷貝的區別,以及實現的方法

談談淺拷貝和深拷貝的區別,以及實現的方法

兩者的區別:一個物件淺複製後,是深層次的物件地址的複製,並沒有開闢新的棧,也就是複製的結果是兩個物件指向同一個地址,修改其中一個物件的屬性,則另一個物件的屬性也會發生改變,而深複製的則是開闢了一個新的棧,兩個物件對應兩個不同的地址,修改一個物件的屬性,不會改變另一個物件的屬性。

話不多說,上程式碼:

// 原始物件
var obj = { 
	a:1, 
	arr: [2,3],
	say:function(){
		console.log('hello')
	},
	obj1:{
		arr:[34,55,5],
		hand:function(){
			console.log('hand')
		},
		obj3:{
			a:1,
			take:function(){
				console.log('take')
			}
		}
	}
};

// 開始淺複製
var shallowObj = shallowCopy(obj);

// 定義淺複製邏輯
function shallowCopy(src) {
  var dst = {};
  for (var prop in src) {
    if (src.hasOwnProperty(prop)) {
      dst[prop] = src[prop];
    }
  }
  return dst;
}

// 改變複製後的新物件屬性值(第一層屬性)
shallowObj.a = 2; 
shallowObj.arr = [9,8];
shallowObj.say = function(){
	console.log('world')
}

// 列印新物件的及方法
console.dir(shallowObj)    
shallowObj.say();  // world
// 列印原物件及方法 console.dir(obj); obj.say();  // hello

結果如圖所示:

結論 : 修改新物件的屬性值,第一層的屬性值的確沒有變化,重點來了,我們給第二層以及更深層次的屬性複製試試

// 原始物件
var obj = { 
	a:1, 
	arr: [2,3],
	say:function(){
		console.log('hello')
	},
	obj1:{
		arr:[34,55,5],
		hand:function(){
			console.log('hand')
		},
		obj3:{
			a:1,
			take:function(){
				console.log('take')
			}
		}
	}
};

// 開始淺複製
var shallowObj = shallowCopy(obj);

// 定義淺複製邏輯
function shallowCopy(src) {
  var dst = {};
  for (var prop in src) {
    if (src.hasOwnProperty(prop)) {
      dst[prop] = src[prop];
    }
  }
  return dst;
}

// 改變複製後的新物件的屬性值(第二層以及更深層次)
shallowObj.obj1.obj3.take = function(){
	console.log('shallowObj_take') 
}
shallowObj.obj1.hand = function(){
	console.log('shallowObj_hand')
}

// 列印新物件的方法呼叫
shallowObj.obj1.obj3.take();  // shallowObj_take
shallowObj.obj1.hand();      // shallowObj_hand

// 列印原物件的方法呼叫
obj.obj1.obj3.take();   // shallowObj_take
obj.obj1.hand();     // shallowObj_hand

問題出現了:原物件的方法被新物件的修改,而產生變化。
原因是複製的是物件的地址指標,兩個屬性共同指向一個物件,只要其一發生變化,另一個也隨之變化

深拷貝的方法:

1.可以遞迴遞迴去複製所有層級屬性

// 原始物件
var obj = { 
	a:1, 
	arr: [2,3],
	say:function(){
		console.log('hello')
	},
	obj1:{
		arr:[34,55,5],
		hand:function(){
			console.log('hand')
		},
		obj3:{
			a:1,
			take:function(){
				console.log('take')
			}
		}
	}
};

// 深複製邏輯(遞迴呼叫)
function deepClone(obj){
    let objClone = Array.isArray(obj)?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判斷obj子元素是否為物件,如果是,遞迴複製
                if(obj[key] && typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,簡單複製
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}    

// 開始深複製
var shallowObj = deepClone(obj);

// 改變複製後的新物件的屬性值(第二層以及更深層次)
shallowObj.obj1.obj3.take = function(){
	console.log('shallowObj_take') 
}
shallowObj.obj1.hand = function(){
	console.log('shallowObj_hand')
}

shallowObj.obj1.obj3.take();  // shallowObj_take
shallowObj.obj1.hand();      // shallowObj_hand

obj.obj1.obj3.take();   // take
obj.obj1.hand();     // hand

結論:深拷貝後改變物件的屬性值,不會影響原始物件的值。

2.除了遞迴,我們還可以借用JSON物件的parse和stringify

function deepClone(obj){
    let _obj = JSON.stringify(obj),
            objClone = JSON.parse(_obj);
    return objClone
}    
let a=[0,1,[2,3],4],
    b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);

3.除了上面兩種方法之外,我們還可以借用JQ的extend方法

$.extend( [deep ], target, object1 [, objectN ] )

deep表示是否深拷貝,為true為深拷貝,為false,則為淺拷貝

target Object型別 目標物件,其他物件的成員屬性將被附加到該物件上。

object1  objectN可選。 Object型別 第一個以及第N個被合併的物件。


let a=[0,1,[2,3],4],
    b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);

相關推薦

談談拷貝拷貝區別以及實現方法

兩者的區別:一個物件淺複製後,是深層次的物件地址的複製,並沒有開闢新的棧,也就是複製的結果是兩個物件指向同一個地址,修改其中一個物件的屬性,則另一個物件的屬性也會發生改變,而深複製的則是開闢了一個新的棧

【js】拷貝拷貝區別以及實現拷貝的方式

一、區別:簡單點來說,就是假設B複製了A,當修改A時,看B是否會發生變化,如果B也跟著變了,說明這是淺拷貝,如果B沒變,那就是深拷貝。 此篇文章中也會簡單闡述到棧堆,基本資料型別與引用資料型別,因為這些概念能更好的讓你理解深拷貝與淺拷貝。 例如: let a=[0,1,2,3,4], b=

python的複製拷貝拷貝區別

在python中,物件賦值實際上是物件的引用。當建立一個物件,然後把它賦給另一個變數的時候,python並沒有拷貝這個物件,而只是拷貝了這個物件的引用 一般有三種方法, alist=[1,2,3,["a","b"]]   (1)直接賦值,傳遞物件的引用而已,原始列表改變,被

引用賦值拷貝拷貝

lan art csdn 理解 article 淺拷貝和深拷貝 blank .net hang 三種引用: http://blog.csdn.net/XIAXIA__/article/details/41652057 深拷貝和淺拷貝的理解: http://blog.csdn

python賦值拷貝拷貝

>>> a = 1 >>> b = a >>> a = 2 >>> a 2 >>> b 1 >>> 你將 1 賦給 a 變數,然後拷貝 a 中的值,將它賦給變數 b。當稍 後將

JavaScript中拷貝拷貝棧堆詳解

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/weixin_40983119/article/details/82995151 簡單來說,JavaScript中單個等於號的賦值就是拷貝,但是呢這個這個賦值可以分為兩種,一種是賦的是資料,一種是賦

java拷貝拷貝區別

淺拷貝是指:只複製一個物件,物件內部存在的指向其他物件陣列或者引用則不復制。 深拷貝是指:不僅複製當前的物件,如果物件中還存在引用,則將引用的物件一起復制。 java中使用到的clone方法是淺拷貝,下面是簡單演示: 首先定義一個簡單類A,申明一個屬性aa = 1;

拷貝拷貝區別.md

淺拷貝和深拷貝的區別: 淺拷貝 對一個已知物件進行拷貝,編譯系統會自動呼叫一種建構函式——拷貝建構函式,如果使用者未定義拷貝建構函式,則會呼叫預設拷貝建構函式,呼叫一次建構函式,呼叫兩次解構函式,兩個物件的指標成員所指記憶體相同,但是程式結束時該記憶體卻被釋放了

賦值、拷貝拷貝區別

首先要知道變數,物件,引用三者之間的關係 變數: 是一個元素, 擁有指向物件的連線空間 **物件:**被分配的一塊記憶體,儲存代表的值 引用: 是變數到物件的指標 一、賦值 在 Python 中,物件的賦值就是簡單的物件引用, 如下所示: a = [1,2,

拷貝拷貝區別實現方法

對於這個問題可以從深拷貝和淺拷貝的使用或起源說起。 1. js變數包含兩種不同資料型別的值基本型別和引用型別 基本型別包括ES6新增的一共是6種,具體如下 string ,number, null ,undefined, boolean ,symbol 引用型

【進階4-1期】詳細解析賦值、拷貝拷貝區別

一、賦值(Copy) 賦值是將某一數值或物件賦給某個變數的過程,分為下面 2 部分 基本資料型別:賦值,賦值之後兩個變數互不影響 引用資料型別:賦址,兩個變數具有相同的引用,指向同一個物件,相互之間有影響 對基本型別進行賦值操作,兩個變數互不影響。 // 木易楊 let a = "muy

拷貝拷貝(談談java中的clone)

clone顧名思義就是複製, 在Java語言中, clone方法被物件呼叫,所以會複製物件。所謂的複製物件,首先要分配一個和源物件同樣大小的空間,在這個空間中建立一個新的物件。那麼在java語言中,有幾種方式可以建立物件呢? 1. 使用new操作

JavaScript中拷貝拷貝區別實現

  JavaScript有兩種資料型別,基礎資料型別和引用資料型別。基礎資料型別都是按值訪問的,我們可以直接操作儲存在變數中的實際的值。而引用型別如Array,我們不能直接操作物件的堆記憶體空間。引用型別的值都是按引用訪問的,即儲存在變數物件中的一個地址,該地址

拷貝拷貝區別

//student.cpp #include "student.h" #include <iostream> #include <string.h> using namespace std; Student::Student() { name = new char(20

引用型別的賦值、拷貝拷貝區別

ICloneable 介面:支援克隆,即用與現有例項相同的值建立類的新例項。 MemberwiseClone 方法:建立當前 System.Object 的淺表副本。 淺拷貝:給物件拷貝一份新的物件。 淺拷貝的定義 —— 只對值型別(或string)型別分配新的記憶

談賦值、拷貝拷貝區別

一:賦值    在Python中,物件的賦值就是簡單的物件引用,這點和C++不同,如下所示:    a = [1,2,'hello',['python','C++']]    b = a    在上述情況下,a和b是一樣的,它們指向同一片記憶體,b不過是a的別名,是引用。我們

python中的拷貝拷貝

div blog deep imp class pri cnblogs 字符串 style 1.淺拷貝 copy.copy() 淺拷貝是拷貝只拷貝最外一層(這裏所說的拷貝是重新生成一個內存地址,也就是只有最外層的地址是重新生成) import copy li=[23,45

【轉】python的拷貝拷貝

end ont code append pen ron 實例 賦值 深拷貝 直接賦值:其實就是對象的引用(別名)。 淺拷貝(copy):拷貝父對象,不會拷貝對象的內部的子對象。 深拷貝(deepcopy): copy 模塊的 deepcopy 方法,完全拷貝了父對象及其

js 對象的拷貝拷貝

tex bject script cnblogs ons assign 對象 而已 obj //淺拷貝,拷貝內存塊,拷貝部門代碼不共存 var obj = { a : "a", b : "b", c : { text : "這是一個文本" } }

java拷貝拷貝

一起 head 有著 cloneabl 獨立 head對象 影響 如果 覆蓋 轉:http://blog.csdn.net/u014727260/article/details/55003402 實現clone的2點: 1,clone方法是Object類的一個方法