浅拷贝
Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
const obj1 = {x: 1, y: 2};
const obj2 = Object.assign({}, obj1);
obj2.x = 2;
console.log(obj1) //{x: 1, y: 2} //原对象未改变
console.log(obj2) //{x: 2, y: 2}
const obj1 = {
x: 1,
y: {
m: 1
}
};
const obj2 = Object.assign({}, obj1);
obj2.y.m = 2;
console.log(obj1) //{x: 1, y: {m: 2}} 原对象也被改变
console.log(obj2) //{x: 2, y: {m: 2}}
赋值所有对象
// 木易杨
function cloneShallow(source) {
var target = {};
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
return target;
}
// 测试用例
var a = {
name: "muyiy",
book: {
title: "You Don't Know JS",
price: "45"
},
a1: undefined,
a2: null,
a3: 123
}
var b = cloneShallow(a);
a.name = "高级前端进阶";
a.book.price = "55";
console.log(b);
// {
// name: 'muyiy',
// book: { title: 'You Don\'t Know JS', price: '55' },
// a1: undefined,
// a2: null,
// a3: 123
// }
Array.concat()
针对数组能实现类似效果的还有slice()和Array.from()等
const arr = [1,2,3,4,[5,6]];
const copy = arr.concat();
copy[0] = 2;
console.log(arr) // [1,2,3,4,[5,6]];
// 改变数组中的引用类型值,原数组也会跟着改变
copy[4][1] = 7
console.log(arr) // [1,2,3,4,[5,7]];
深拷贝
JSON.parse()和JSON.stringify()
const obj1 = {
x: 1,
y: {
m: 1
}
};
const obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1) //{x: 1, y: {m: 1}}
console.log(obj2) //{x: 1, y: {m: 1}}
obj2.y.m = 2;
console.log(obj1) //{x: 1, y: {m: 1}} 原对象未改变
console.log(obj2) //{x: 2, y: {m: 2}}
这种方法使用较为简单,可以满足基本日常的深拷贝需求,而且能够处理JSON格式能表示的所有数据类型,但是有以下几个缺点:
- undefined、任意的函数、正则表达式类型以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时);
- 它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object;
- 如果对象中存在循环引用的情况无法正确处理。