深拷贝和浅拷贝
- 深拷贝:改变拷贝后的结果,不会影响拷贝之前的内容
- 浅拷贝:改变拷贝后的结果,会影响拷贝之前的内容
最常用的 es6 ...扩展运算符 实现拷贝
// 单层对象 -- 深拷贝
let obj = {name: 'mushi', age: 28}
let copy = {...obj}
obj.age = 29
console.log(obj, copy) // { name: 'mushi', age: 29 } { name: 'mushi', age: '28' }
// 对象嵌套 -- 浅拷贝
let obj1 = {name: 'mushi', age: 28, job: [1,2]}
let copy1 = {...obj1}
obj1.job.push(3)
console.log(obj1, copy1) // { name: 'mushi', age: 28, job: [ 1, 2, 3 ] } { name: 'mushi', age: 28, job: [ 1, 2, 3 ] }
Object.assign() 实现拷贝
// 单层对象 -- 深拷贝
let obj = {name: 'mushi', age: 28}
let copy = Object.assign({}, obj)
obj.age = 29
console.log(obj, copy) // { name: 'mushi', age: 29 } { name: 'mushi', age: '28' }
// 对象嵌套 -- 浅拷贝
let obj1 = {name: 'mushi', age: 28, job: [1, 2]}
let copy1 = Object.assign({}, obj1)
obj1.job.push(3)
console.log(obj1, copy1) // { name: 'mushi', age: 28, job: [ 1, 2, 3 ] } { name: 'mushi', age: 28, job: [ 1, 2, 3 ] }
Array.slice() 和 Array.concat()
// 单层数组 -- 深拷贝
let a = [1,2,3]
let b = a.slice(); // let b = a.concat([])
a.push(4)
console.log(a, b) // [ 1, 2, 3, 4 ] [ 1, 2, 3 ]
// 嵌套数组 -- 浅拷贝
let c = [1,2,3, ['a', 'b']]
let d = c.slice(); // let d = c.concat([])
c[3].push('c')
console.log(c, d) // [ 1, 2, 3, [ 'a', 'b', 'c' ] ] [ 1, 2, 3, [ 'a', 'b', 'c' ] ]
JSON.parse 和 JSON.stringify实现深拷贝
- 效率比较低
- 不能实现复杂的深拷贝Map, Set, RegExp, Date, ArrayBuffer 和其他内置类型在进行序列化时会丢失
let obj = {a: 1, b: 2, c: {d: 3}}
let copy = JSON.parse(JSON.stringify(obj))
obj.c.d = 300
console.log(obj, copy) // { a: 1, b: 2, c: { d: 300 } } { a: 1, b: 2, c: { d: 3 } }
对象中包含一些内置对象或者函数对象
// 拷贝函数对象会丢失
let obj = {a: 1, b: () => {}}
let copy = JSON.parse(JSON.stringify(obj))
obj.a = 2
console.log(obj, copy) // { a: 2, b: [Function: b] } { a: 1 }
// 拷贝内置对象会丢失
let obj1 = {a: 1, b: new RegExp()}
let copy1 = JSON.parse(JSON.stringify(obj1))
obj1.a = 2
console.log(obj1, copy1) // { a: 2, b: /(?:)/ } { a: 1, b: {}}
自己封装deepCopy函数进行深拷贝
- 利用for in 循环进行拷贝
- 排除一些其他异常数据
- 使用new WeakMap()对拷贝过的数据进行存储防止重复循环引用
- 递归循环
function deepCopy (obj, hash = new WeakMap()) {
if (obj === null || obj === undefined) return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (typeof obj !== 'object') return obj; // 函数是不需要深拷贝的
if (hash.get(obj)) return hash.get(obj); // 如果obj被拷贝过就直接返回
let cloneObj = new obj.constructor; // 申明一个cloneObj类型obj保持一致
hash.set(obj, cloneObj) // 将当前对象和拷贝对象存入hash中
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepCopy(obj[key], hash)
}
}
return cloneObj
}
let obj = {a: 1, b: {c: 2, d: 3}}
let copy = deepCopy(obj);
obj.a = 100
console.log(obj, copy) // { a: 100, b: { c: 2, d: 3 } } { a: 1, b: { c: 2, d: 3 } }
网友评论