一.从简单类型和复杂类型数据的存储来认识深拷贝
二.区分常用操作是深拷贝还是浅拷贝:
1.= 赋值
不论是简单的对象或数组还是复杂的对象或数组,都是浅拷贝
以简单数组示例:
let arr = [1, 2, 3]
let newArr = arr
newArr[0] = 0
console.log(arr[0]) // 0
2.循环赋值
简单的对象或数组可以实现深拷贝,复杂的对象或数组,内部的复杂类型数据是浅拷贝
以对象示例:
let obj = {
key1: 1,
key2: [1, 2, 3]
}
let newObj = {}
for (let i in obj) {
newObj[i] = obj[i]
}
newObj.key1 = 0
newObj.key2[0] = 0
console.log(obj.key1) // 1 简单类型数据实现了深拷贝
console.log(obj.key2[0]) // 0 复杂类型数据是浅拷贝
注意:如果直接将复杂数据类型整体替换,则互不影响
newObj.key2 = []
console.log(obj.key2) // [1, 2, 3]
3.Object.assign(newObj, obj)(ES6)和循环赋值相同
三.深拷贝实现
1.不含函数的对象可以使用JSON.parse()和JSON.stringify()进行深拷贝(函数键值对会忽略)
let obj = {
key1: 1,
key2: {
key2_key1: 2
}
}
let newObj = {}
newObj = JSON.parse(JSON.stringify(obj))
newObj.key1 = 0
newObj.key2.key2_key1 = 0
console.log(obj.key1) // 1
console.log(obj.key2.key2_key1) // 2
2.循环递归
对象的属性值不会引用外层对象的情况(否则会进入死循环):
function deepCopy(obj) {
let newObj = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === "object") {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
// 如果子属性为引用数据类型,递归复制
if (obj[i] && typeof obj[i] === "object") {
newObj[i] = deepCopy(obj[i])
} else {
// 如果是基本数据类型,只是简单的复制
newObj[i] = obj[i]
}
}
}
}
return newObj
}
deepClone (obj) {
var _obj
if (typeof obj === 'object' && obj !== null) {
// object
if (Object.prototype.toString.call(obj) === '[object Object]') {
_obj = {}
for (var key in obj) {
_obj[key] = deepClone(obj[key])
}
return _obj
} else if (Object.prototype.toString.call(obj) === '[object Array]') { // Array
_obj = []
for (var _key in obj) {
_obj[_key] = deepClone(obj[_key])
}
return _obj
} else {
return obj
}
} else {
return obj
}
}
包含对象的属性值引用外层对象的情况:
function deepCopy(obj) {
var newObj = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === "object") {
for (leti in obj) {
let prop = obj[i] // 避免相互引用造成死循环,如obj.a=obj
if (prop == obj) {
continue
}
if (obj.hasOwnProperty(i)) {
// 如果子属性为引用数据类型,递归复制
if (prop && typeof prop === "object") {
newObj[i] = (prop.constructor === Array) ? [] : {}
arguments.callee(prop, newObj[i]) // 递归调用
} else {
// 如果是基本数据类型,只是简单的复制
newObj[i] = prop
}
}
}
}
return newObj
}
https://segmentfault.com/a/1190000021682472
参考:
一篇文章彻底说清JS的深拷贝/浅拷贝https://segmentfault.com/a/1190000012828382
JS深拷贝和浅拷贝的实现https://www.jianshu.com/p/cf1e9d7e94fb