一、概念
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
二、浅拷贝的实现方式
-
Object.assign()
Object.assign()
方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是Object.assign()
进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
注意:当object只有一层的时候,是深拷贝
-
Array.prototype.concat()
修改新对象会改到原对象:
-
Array.prototype.slice()
修改新对象会改到原对象:
三、深拷贝的实现方式
JSON.parse(JSON.stringify())
let arr = [1, 3, {username: 'kobe'}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'libai';
console.log(arr, arr4)
原理:用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
弊端:
(1)序列化反序列化十分耗性能;
(2)如果遇到key是js函数或者js关键字,会自动跳过。
- 手写深拷贝
function deepClone(sourceObj){
//建立新容器
const targetObj = sourceObj.constructor === Array ? [] : {}
// 遍历
for(let keys in sourceObj){
if(sourceObj.hasOwnProperty(keys)){
// 判断是基础数据类型还是引用数据类型,如果是引用数据类型
if(targetObj[keys] && typeof sourceObj[keys] === 'Object'){
targetObj[keys] = sourceObj[keys].constructor === Array ? [] : {}
targetObj[keys] = deepClone(sourcrObj[keys])
} else {
// 基本数据类型
targetObj[keys] = sourceObj[keys]
}
}
}
return targetObj
}
let sourceObj = {
num: 12,
str: 'xxx',
bol: false,
// 函数的处理一般只是功能的复用
fn: function(){console.log('6')},
// 也不需要处理
nulVal: null,
// 无元素,可以直接通过构造函数new出来的
reg: /7/,
date: new Date(),
// 新结构
map: new Map([['d', 8], ['c', 4]]),
set: new Set([10, 11]),
//[key+value]
array: [1,2],
arrayofobj: [{a: 3, b: 4}],
obj: {c: 5}
}
- 函数库lodash
该函数库也有提供_.cloneDeep用来做 Deep Copy
var _ = require('lodash');
var obj = {
a: 1,
b: {f: {g: 1}},
c: [1, 2, 3]
}
var obj2 = _.cloneDeep(obj);
console.log(obj.b.f == obj2.b.f)