詳細解析賦值 淺拷貝和深拷貝的區別

2021-10-21 15:04:04 字數 4159 閱讀 7854

賦值是將某一數值或物件賦給某個變數的過程,分為下面 2 部分

對基本型別進行賦值操作,兩個變數互不影響。

// 木易楊

let a = "muyiy";

let b = a;

console.log(b);

// muyiy

a = "change";

console.log(a);

// change

console.log(b);

// muyiy

複製**

對引用型別進行賦操作,兩個變數指向同乙個物件,改變變數 a 之後會影響變數 b,哪怕改變的只是物件 a 中的基本型別資料。

// 木易楊

let a =

}let b = a;

console.log(b);

// // }

a.name = "change";

a.book.price = "55";

console.log(a);

// // }

console.log(b);

// // }

複製**

通常在開發中並不希望改變變數 a 之後會影響到變數 b,這時就需要用到淺拷貝和深拷貝。

1、什麼是淺拷貝

建立乙個新物件,這個物件有著原始物件屬性值的乙份精確拷貝。如果屬性是基本型別,拷貝的就是基本型別的值,如果屬性是引用型別,拷貝的就是記憶體位址 ,所以如果其中乙個物件改變了這個位址,就會影響到另乙個物件。

上圖中,sourceobject是原物件,其中包含基本型別屬性field1和引用型別屬性refobj。淺拷貝之後基本型別資料field2filed1是不同屬性,互不影響。但引用型別refobj仍然是同乙個,改變之後會對另乙個物件產生影響。

簡單來說可以理解為淺拷貝只解決了第一層的問題,拷貝第一層的基本型別值,以及第一層的引用型別位址

2、淺拷貝使用場景

object.assign()方法用於將所有可列舉屬性的值從乙個或多個源物件複製到目標物件。它將返回目標物件。

有些文章說object.assign()是深拷貝,其實這是不正確的。

// 木易楊

let a =

}let b = object.assign({}, a);

console.log(b);

// // }

a.name = "change";

a.book.price = "55";

console.log(a);

// // }

console.log(b);

// // }

複製**

上面**改變物件 a 之後,物件 b 的基本屬性保持不變。但是當改變物件 a 中的物件book時,物件 b 相應的位置也發生了變化。

通過**可以看出實際效果和object.assign()是一樣的。

slice()方法返回乙個新的陣列物件,這一物件是乙個由beginend(不包括end)決定的原陣列的淺拷貝。原始陣列不會被改變。

// 木易楊

let a = [0, "1", [2, 3]];

let b = a.slice(1);

console.log(b);

// ["1", [2, 3]]

a[1] = "99";

a[2][0] = 4;

console.log(a);

// [0, "99", [4, 3]]

console.log(b);

// ["1", [4, 3]]

複製**

可以看出,改變a[1]之後b[0]的值並沒有發生變化,但改變a[2][0]之後,相應的b[1][0]的值也發生變化。說明slice()方法是淺拷貝,相應的還有concat等,在工作中面對複雜陣列結構要額外注意。

1、什麼是深拷貝

深拷貝會拷貝所有的屬性,並拷貝屬性指向的動態分配的記憶體。當物件和它所引用的物件一起拷貝時即發生深拷貝。深拷貝相比於淺拷貝速度較慢並且花銷較大。拷貝前後兩個物件互不影響。

2、深拷貝使用場景

json.parse(json.stringify(object))

// 木易楊

let a =

}let b = json.parse(json.stringify(a));

console.log(b);

// // }

a.name = "change";

a.book.price = "55";

console.log(a);

// // }

console.log(b);

// // }

複製**

完全改變變數 a 之後對 b 沒有任何影響,這就是深拷貝的魔力。

我們看下對陣列深拷貝效果如何。

// 木易楊

let a = [0, "1", [2, 3]];

let b = json.parse(json.stringify( a.slice(1) ));

console.log(b);

// ["1", [2, 3]]

a[1] = "99";

a[2][0] = 4;

console.log(a);

// [0, "99", [4, 3]]

console.log(b);

// ["1", [2, 3]]

複製**

對陣列深拷貝之後,改變原陣列不會影響到拷貝之後的陣列。

但是該方法有以下幾個問題。

1、會忽略undefined

2、會忽略symbol

3、不能序列化函式

4、不能解決迴圈引用的物件

5、不能正確處理new date()

6、不能處理正則

解決方法轉成字串或者時間戳就好了。

// 木易楊

let date = (new date()).valueof();

// 1545620645915

json.stringify(date);

// "1545620673267"

json.parse(json.stringify(date));

// 1545620658688

複製**

ps:為什麼會存在這些問題可以學習一下 json。

除了上面介紹的深拷貝方法,常用的還有jquery.extend()lodash.clonedeep(),後面文章會詳細介紹原始碼實現,敬請期待!

和原資料是否指向同一物件

第一層資料為基本資料型別

原資料中包含子物件賦值是

改變會使原資料一同改變

改變會使原資料一同改變

淺拷貝否

改變會使原資料一同改變

改變會使原資料一同改變

深拷貝否

改變會使原資料一同改變

改變會使原資料一同改變

Python詳細解析 深拷貝,淺拷貝,賦值

假設我們另x 1,2,3,4,5 y x,如果我們改變x的值,y的值會不會也跟著變化,答案是會的,因為賦值後雖然y的值和x的值是一樣的,但是他們對應的引用還是相同的,如果改變了x其中乙個裡面的值,y中對應位置的元素也會改變,如下圖 x 1,2,3,4 y xprint y 結果 1,2,3,4 x ...

淺拷貝 深拷貝和淺賦值 深賦值

include includeusing namespace std class string else 淺拷貝 也就是系統預設的拷貝,可寫可不寫。string const string s 預設的拷貝構造 深拷貝 string const string s string s2 s1 深賦值 str...

賦值 淺拷貝和深拷貝

三種方法的形式存在一定的類似,但是也存在各個之間不相同的地方。淺拷貝和深拷貝是用在物件 object 或者陣列 array 這樣的資料型別拷貝賦值時候的說法,而賦值操作也可以用在基礎的資料型別,如number string等 賦值 對於物件型別資料的影響 賦於該值在棧中的位址,而不是堆中的資料,使得...