一、浅拷贝和深拷贝的定义
浅拷贝:浅拷贝只是拷贝一层更深层次对象级别的只拷贝引用。
深拷贝:深拷贝拷贝多层,每一级别的数据都会拷贝。
二、浅拷贝和深拷贝的区别
浅拷贝和深拷贝都创建出一个新的对象,但在复制对象属性的时候,行为就不一样
- 浅拷贝只复制属性指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象属性会影响原对象
- 深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
三、浅拷贝的实现
-
- for···in只循环第一层
// 只复制第一层的浅拷贝
function simpleCopy(obj1) {
var obj2 = Array.isArray(obj1) ? [] : {};
for (let i in obj1) {
obj2[i] = obj1[i];
}
return obj2;
}
var obj1 = {
a: 'A',
b: 'B',
c: {
d: 'D'
}
}
var obj2 = simpleCopy(obj1);
obj2.a = 'C';
obj2.c.d = 'E';
console.log(obj1.a); // A
console.log(obj2.a); // C
console.log(obj1.c.d); // E
console.log(obj2.c.d); // E
- Object.assign方法
ES6中的Object.assign方法,Object.assign是ES6的新函数。Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
var obj1 = {
a: "A",
b: {
a: "C",
b: 21
}
};
var cloneObj1 = Object.assign({}, obj1);
cloneObj1.a = "DF";
cloneObj1.b.a = "JK";
console.log(obj1.a); //A
console.log(obj1.b.a); // JK
- 直接用=赋值 和 拓展运算符
let a = ['A', 'B', 'C', 'D', 'E'],
b = a;
console.log(a === b); //true
a[0] = 1;
console.log(a, b); // 1 'B', 'C', 'D', 'E'
const expandArr = ["A", "B", "C"];
const expandArrs = [...expandArr];
expandArr[1] = "JK";
console.log(expandArr); // ["A", "JK", "C"]
console.log(expandArrs); // ["A", "B", "C"]
四、深拷贝的实现
- 采用递归去拷贝所有层级属性
function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
//判断ojb子元素是否为对象,如果是,递归复制
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone(obj[key]);
} else {
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a = ['A', 'B', 'C', 'D'],
b = deepClone(a);
a[0] = 'J';
console.log(a, b); // a['J', 'B', 'C', 'D'] b ['A', 'B', 'C', 'D']
- 利用 JSON 对象实现深拷贝
用JSON.stringify
把对象转成字符串,再用JSON.parse
把字符串转成新的对象。
// 深拷贝拷贝多层, 每一级别的数据都会拷贝.
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
},
color: ['pink', 'red']
};
// 2. 利用 JSON 对象
function deepCopy(obj) {
let _obj = JSON.stringify(obj);
let newObj = JSON.parse(_obj);
return newObj;
}
let newObj = deepCopy(obj);
newObj.msg.age = 22;
console.log(newObj); // newObj.msg.age = 22
console.log(obj); // obj.msg.age 还是等于 18 没有改变
五、总结
浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值那种,会拷贝其本身,如果除了基本数据类型之外还有一层对象,那么对于浅拷贝而言就只能拷贝其引用,对象的改变会反应到拷贝对象上,但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。