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); //
复制代码