如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制
了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝;如果B没变,那就是深拷贝。
(上面的复制在程序中可以看做是赋值关系)
一、多层嵌套的深拷贝
1、封装函数——遍历的方式实现对象/数组深拷贝
// 深拷贝函数
const deepCopy = (obj) => {
const cloneTarget = Array.isArray(obj) ? [] : {};
if (obj === null) return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (typeof obj !== 'object') return obj;
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneTarget[key] = deepCopy(obj[key]);
}
}
return cloneTarget;
}
const objTest = {
date: new Date(),
reg: new RegExp(/[a-z]/g),
fn: () => { console.log(1) },
a: 1,
arr: [1, [2, 3]],
obj: {
name: 'winne',
like: ['a', 'b']
},
b: null,
}
console.log(deepCopy(objTest))
// ------------分割线---------------------
var obj = {
a:1,
b:{bb:2},
c:[1,2,3]
}
var arr = [1,2,3,4,5,[22,33,[44,88]]]
var copyObj = deepCopy(obj);
// var copyObj = obj; // 如果不进行深拷贝,那么修改copyObj的时候原先对象也会受到影响
copyObj.b.bb = 111;
console.log(obj)
console.log(copyObj)
var copyArr = deepCopy(arr);
// var copyArr = arr; // 如果不进行深拷贝,那么修改copyArr的时候原先数组也受到影响
copyArr[5].push(999)
console.log(arr)
console.log(copyArr)
2、JSON.parse/JSON.stringify方式——实现对象/数组的深拷贝
使用这个方法来进行深拷贝,如果对象中存在undefined、任意的函数以及 symbol 作为对象属性值时 JSON.stringify() 对跳过(忽略)它们进行序列化
的隐患。
详细阅读:JSON.stringify() 九大特性
// 对象
var obj = {
a:1,
b:{bb:2},
c:[1,2,3]
}
var copyObj = JSON.parse( JSON.stringify(obj) ) // 这里实现了对obj的深拷贝
copyObj.b.bb = 666
console.log(obj) // {a:1,b:{bb:2},c:[1,2,3]}
console.log(copyObj) // {a:1,b:{bb:666},c:[1,2,3]}
// 数组
var arr = [1, 2, [6], 7, [8, [9]]]
var copyArr = JSON.parse(JSON.stringify(arr)) // 这里实现了对arr的深拷贝
copyArr[2].push(0)
console.log(arr) // [1, 2, [6], 7, [8, [9]]]
console.log(copyArr) // [1, 2, [6, 0], 7, [8, [9]]]
二、一层数组或对象的深拷贝
1、slice()—— 一层数组的深拷贝
var arr = [1, 2, 3]
var newArr = arr.slice()
arr.push(4)
console.log(arr) // [1, 2, 3, 4]
console.log(newArr) // [1, 2, 3]
2、concat()—— 一层数组的深拷贝
var arr = [1, 2, 3]
var newArr = arr.concat()
arr.push(4)
console.log(arr) // [1, 2, 3, 4]
console.log(newArr) // [1, 2, 3]
3、解构赋值—— 一层数组 / 对象的深拷贝
// 数组
var arr = [1, 2, 3]
var newArr = [...arr]
arr.push(4)
console.log(arr) // [1, 2, 3, 4]
console.log(newArr) // [1, 2, 3]
// 对象
var obj = { name: 'winne' }
var newObj = { ...obj }
obj.name = 'xf'
console.log(obj) // {name: "xf"}
console.log(newObj) // {name: "winne"}
4、Object.assign()—— 一层对象的深拷贝
var obj = { name: 'winne' }
var newObj = Object.assign({}, obj)
obj.age = 20
console.log(obj) // {name: "winne", age: 20}
console.log(newObj) // {name: "winne"}
5、filter()—— 一层数组的深拷贝
var arr = [1, 2]
var newArr = arr.filter((item) => {
return true
})
arr.push(88)
console.log(arr) // [1, 2, 88]
console.log(newArr) // [1, 2]
6、map()—— 一层数组的深拷贝
var arr = [1, 2]
var newArr = arr.map((item) => {
return item
})
arr.push(88)
console.log(arr) // [1, 2, 88]
console.log(newArr) // [1, 2]
参考原文:
https://www.cnblogs.com/renbo/p/9563050.html