let a = {
?????name: 'Dobby',
?????age: 20
?};
?let b = a;
?a.age = 10;
?b.name = ' qzhang';
?console.log(b.age); // output:10
?console.log(a.name); // output:qzhang
從上面例子可以看出,當(dāng)我們把一個(gè)對象賦值給一個(gè)變量的時(shí)候,兩者的值會是同一個(gè)引用,其中一方改變,另一方也會改變。
通常我們在開發(fā)的過程中不希望出現(xiàn)這樣的問題,我們可以使用淺拷貝來解決這個(gè)問題。
淺拷貝
首先,可以通過 Object.assign 來解決這個(gè)問題。
let a = {?
? ? ? name: 'Dobby',?
? ? ? age: 20? ?
};? ?
let b = Object.assign({}, a);? ?
a.age = 10;? ?
b.name = ' qzhang'; ?
console.log(b.age); // output:20?
console.log(a.name); // output:Dobby
還可以使用 展開運(yùn)算符(...)來解決。
let a = {?
? ? ? ?name: 'Dobby',?
? ? ? ?age: 20? ?
};? ?
let b = {...a};? ?
a.age = 10;? ?
b.name = ' qzhang'; ?
console.log(b.age); // output:20?
console.log(a.name); // output:Dobby
通常淺拷貝可以解決大部分問題,但當(dāng)我們在如下例子中對象中還有對象的話,就需要深拷貝了。
let a = {
?????name: 'Dobby',
?????age: 20,
?????job: {
?????????first: 'web'
?????}
?};
?let b = {...a};
?a.age = 10;
?a.job.first = 'java';
?console.log(b.age); // output:20
?console.log(b.job.first); // output:java
深拷貝
通常可以通過 JSON.parse(JSON.stringify(object)) 來解決。
let a = {
?????name: 'Dobby',
?????age: 20,
?????job: {
?????????first: 'web'
?????}
?};
?let b = JSON.parse(JSON.stringify(a));
?a.job.first = 'java';
?console.log(b.job.first); // output:web
但該方法有局限性:
1. 會忽略 undefined
2. 會忽略 symbol
3. 不能序列化函數(shù)
4. 不能解決循環(huán)引用的對象
通常情況下,復(fù)雜數(shù)據(jù)都是可以序列化的,所以這個(gè)函數(shù)可以解決大部分問題,并且該函數(shù)是內(nèi)置函數(shù)中處理深拷貝性能最快的。如果數(shù)據(jù)中有 undefined、symbol、函數(shù)三種情況,可以使用 lodash 的深拷貝函數(shù)。