js
中深拷貝與淺拷貝的概念。undefined
,boolean
,number
,string
,null
,symbol
。var str = 'abc123';
str.replace('abc', 123); // '123123'
console.log(str); // 'abc123'
複製代碼
Object
,Array
,Function
,Math
,Data
,RegExp
等)。基本數據類型
的拷貝都是深拷貝。// 對基本數據類型的直接賦值是深拷貝
var a = 1;
b = a;
a = 2;
console.log(a); // 2
console.log(b); // 1
// 對引用數據類型的直接賦值是淺拷貝(拷貝的是引用的地址)
var obj1 = { name: 'ZhangSan', age: 21 };
var obj2 = obj1;
obj1.age = 32;
console.log(obj1.age); // 32
console.log(obj2.age); // 32
複製代碼
引用數據類型
來闡述的// 淺拷貝,直接賦值
var a = [1,2,3,4,5];
var b = a;
a[0] = 2;
console.log(a); // [2, 2, 3, 4, 5]
console.log(b); // [2, 2, 3, 4, 5]
複製代碼
// cancat,簡單數組的深拷貝
var a = [1,2,3,4,5];
var b = [].concat(a);
a[0] = 2;
console.log(a); // [2, 2, 3, 4, 5]
console.log(b); // [1, 2, 3, 4, 5]
複製代碼
// slice,簡單數組的深拷貝
var a = [1,2,3,4,5];
var b = a.slice();
a[0] = 2;
console.log(a); // [2, 2, 3, 4, 5]
console.log(b); // [1, 2, 3, 4, 5]
複製代碼
// ...運算符,簡單數組的深拷貝
var a = [1,2,3,4,5];
var b = [...a];
a[0] = 2;
console.log(a); // [2, 2, 3, 4, 5]
console.log(b); // [1, 2, 3, 4, 5]
複製代碼
cancat
,slice
,...運算符
的不足var a = [1,[1,2],3,4,5];
var b = a.slice();
a[0] = 2;
a[1][0] = 2;
console.log(a); // [2, [2,2], 3, 4, 5]
console.log(b); // [1, [2,2], 3, 4, 5]
複製代碼
var a = [1,[1,2],3,4,5];
var b = [].concat(a);
a[0] = 2;
a[1][0] = 2;
console.log(a); // [2, [2,2], 3, 4, 5]
console.log(b); // [1, [2,2], 3, 4, 5]
複製代碼
var a = [1,[1,2],3,4,5];
var b = [...a];
a[0] = 2;
a[1][0] = 2;
console.log(a); // [2, [2,2], 3, 4, 5]
console.log(b); // [1, [2,2], 3, 4, 5]
複製代碼
從上面的結果能夠看到,cancat
,slice
,...運算符
只能對數組的一級元素爲基本類型的數據實現深拷貝,對於引用類型的元素仍是淺拷貝。數組
...運算符
var obj1 = {
name: 'ZhangSan',
age: 24,
team: {
name: 'obj1',
number: 10
}
};
var obj2 = {...obj1};
obj1.name = 'LiSi';
obj1.age = 42;
obj1.team.name = 'test';
obj1.team.number = 20;
console.log(obj1); // {name: "LiSi", age: 42, team: {name: "test", number: 20}}
console.log(obj2); // {name: "ZhangSan", age: 24, team: {name: "test", number: 20}}
複製代碼
Object.assign()
方法var obj1 = {
name: 'ZhangSan',
age: 24,
team: {
name: 'obj1',
number: 10
}
};
var obj2 = Object.assign({}, obj1);
obj1.name = 'LiSi';
obj1.age = 42;
obj1.team.name = 'test';
obj1.team.number = 20;
console.log(obj1); // {name: "LiSi", age: 42, team: {name: "test", number: 20}}
console.log(obj2); // {name: "ZhangSan", age: 24, team: {name: "test", number: 20}}
複製代碼
從上面能夠看到...運算符
和 Object.assign()
方法也只能實現對一級數據爲基本數據類型的拷貝,對於一級數據類型爲引用類型的數據沒法實現深拷貝。bash
JSON.parse
和JSON.stringify
var a = [1,[1,2],3,4,5];
var b = JSON.parse(JSON.stringify(a));
a[0] = 2;
a[1][0] = 2;
console.log(a); // [2, [2,2], 3, 4, 5]
console.log(b); // [1, [1,2], 3, 4, 5]
複製代碼
var obj1 = {
name: 'ZhangSan',
age: 24,
team: {
name: 'obj1',
number: 10
}
};
var obj2 = JSON.parse(JSON.stringify(obj1));
obj1.name = 'LiSi';
obj1.age = 42;
obj1.team.name = 'test';
obj1.team.number = 20;
console.log(obj1); // {name: "LiSi", age: 42, team: {name: "test", number: 20}}
console.log(obj2); // {name: "ZhangSan", age: 24, team: {name: "obj1", number: 10}}
複製代碼
ps: 並非全部的數據類型均可以被JSON.stringify
。ui
// 此方法僅僅提供思路,並不是最佳實踐
function deepClone(target, type) { // target:目標對象,type:true/false =>深拷貝/淺拷貝,默認false
if(!type) return target
const baseType = ['string','number','boolean','undefined','null','symbol']
if(!target || baseType.includes(typeof target)) return target
let cloneData = Array.isArray(target) ? [] : {};
if(typeof target === 'object') {
for(key in target) {
if(target.hasOwnProperty(key)) {
if(target[key] && typeof target[key] ==="object") {
cloneData[key] = deepClone(target[key], true);
} else {
cloneData[key] = target[key];
}
}
}
}
return cloneData
}
var obj1 = {
name: 'ZhangSan',
age: 24,
team: {
name: 'obj1',
number: 10,
person: {
name: '二狗子',
sex: '女'
}
}
};
var obj2 = deepClone(obj1, true);
obj1.name = 'LiSi';
obj1.age = 42;
obj1.team.name = 'test';
obj1.team.number = 20;
obj1.team.person = {
name: '劉二哈',
sex: '男'
}
console.log(obj1); //
console.log(obj2); //
複製代碼