目录
前言
我们知道JavaScript中分为基础数据类型和引用数据类型,对于基础数据而言,没有深浅拷贝之分。深浅拷贝对于引用数据来说的。
浅拷贝的定义
对象的浅拷贝是其属性与拷贝源对象的属性共享相同引用(指向相同的底层值)的副本。因此,当你更改源或副本时,也可能导致其他对象也发生更改——也就是说,你可能会无意中对源或副本造成意料之外的更改。这种行为与深拷贝的行为形成对比,在深拷贝中,源和副本是完全独立的。
通俗来说浅拷贝就是复制了引用, 并不是完全复制了值。
例如下面例子用=进行了一个浅拷贝,由于都指向同一个引用,修改其中一个会导致都发生改变
const originArray = [1,2,3,4,5];
const newArray = originArray;
newArray.push(6);
console.log(originArray) // [1,2,3,4,5,6]
console.log(newArray) // [1,2,3,4,5,6]
浅拷贝实现方式
Array.prototype.concat()
Array.prototype.slice()
Array.from()
Object.assign()
Object.create()
还有es的展开运算符 // [.......obj]
深拷贝的定义
对象的深拷贝是指其属性与其拷贝的源对象的属性不共享相同的引用(指向相同的底层值)的副本。因此,当你更改源或副本时,可以确保不会导致其他对象也发生更改;也就是说,你不会无意中对源或副本造成意料之外的更改。这种行为与浅拷贝的行为形成对比,在浅拷贝中,对源或副本的更改可能也会导致其他对象的更改(因为两个对象共享相同的引用)。
通俗的来说深拷贝就是复制完后互不影响的新个体
深拷贝实现方式
1.JSON 对象中的 parse 和 stringify,前提是可序列化的对象
let originArray = [1, 2, 3, 4, 5]
let newArray = JSON.parse(JSON.stringify(originArray))
newArray.push(6);
console.log(originArray) // [1,2,3,4,5]
console.log(newArray) // [1,2,3,4,5,6]
注意,以下JavaScript对象是无法进行序列化
所有安全的 JSON 值可以进行JSON序列化,安全的 JSON 值是指能够呈现为有效 JSON 格式的值。我们来看看什么是不安全的JSON 值 。 undefined 、 function 、 symbol (ES6+)和包含循环引用(对象之间相互引用,形成一个无限循环)的对象都不符合 JSON 结构标准,支持 JSON 的语言无法处理它们。
例如,下面这个对象经过深拷贝后丢失了sayHello函数,原因就是函数在序列化中会被忽略
const originObj = {
name:'axuebin',
sayHello:function(){
console.log('Hello World');
}
}
console.log(originObj); // {name: "axuebin", sayHello: ƒ}
const cloneObj = JSON.parse(JSON.stringify(originObj));
console.log(cloneObj); // {name: "axuebin"}
2.递归
递归实现的思路:对每层对象都进行新创建对象=》赋值的操作
function deepClone(source) {
const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
for (let keys in source) { // 遍历目标
if (source.hasOwnProperty(keys)) {
targetObj[keys] = source[keys];
}
}
return targetObj;
}
3.深克隆循环引用的对象
function deepClone(obj) {
const objectMap = new Map()
const _deepClone = (value) => {
const type = typeof value
// 判断克隆的值不是对象就知道返回,注意typeof null 返回的也是object
if (type !== 'object' || type === null) {
return value
}
if (objectMap.has(value)) {
return objectMap.get(value)
}
// 处理数组和对象
const result = Array.isArray(value) ? [] : {};
objectMap.set(value, result)
for (const key in value) {
result[key] = _deepClone(value[key])
}
return result
}
return _deepClone(obj)
}
总结
1.JavaScript 内置对象方法实现的大部分都是浅拷贝
2.JSON 对象中的 parse 和 stringify可实现深拷贝,但对数据有要求
3.递归实现深拷贝方式最佳