JavaScript对象类型数据深拷贝方法【主要解决JSON.parse(JSON.stringify()会去掉函数属性的问题】
正常情况下,在js中我们要对一个数组做深拷贝,最新想到的方法是JSON.parse(JSON.stringify(arr)),但是JSON.parse(JSON.stringify()会去掉属性中为函数的属性。
例如:
let arr = [
{
a: 1,
b: 2,
c: function () {
console.log('111');
}
}
]
arr1 = JSON.parse(JSON.stringify(arr))
arr1[0].a = 100
console.log(arr, arr1);
// [ { a: 1, b: 2, c: [Function: c] } ]
// [ { a: 100, b: 2 } ]
手写对象类型数据深拷贝方法deepClone
代码如下:
function deepClone(originValue) {
// 如果不是对象类型且是null则直接将当前值返回
if (typeof originValue !== 'object' || originValue == null) {
return originValue;
}
const newObject = Array.isArray(originValue) ? [] : {}
for (const key in originValue) {
// 因为javascript没有将hasOwnProperty作为一个敏感词,所以我们很有可能将对象的一个属性命名为hasOwnProperty,
// 这样一来就无法再使用对象原型的 hasOwnProperty 方法来判断属性是否是来自原型链。
// 所以采用 Object.prototype.hasOwnProperty.call
if (Object.prototype.hasOwnProperty.call(originValue, key)) {
// 若是对象类型属性,递归调用deepClone,若是其他类型属性,则直接赋值
if (typeof originValue[key] === 'object' && originValue[key] !== null) {
newObject[key] = deepClone(originValue[key]);
} else {
newObject[key] = originValue[key];
}
}
}
return newObject
}
let arr = [
{
a: 1,
b: 2,
c: function () {
console.log('111');
}
}
]
arr1 = deepClone(arr)
// arr1 = JSON.parse(JSON.stringify(arr))
arr1[0].a = 100
console.log(arr, arr1);
// [ { a: 1, b: 2, c: [Function: c] } ]
// [ { a: 100, b: 2, c: [Function: c] } } ]
arr1[0].c() // 111
小结
如果对象数组中属性没有函数属性,可以使用JSON.parse(JSON.stringify()
,但是如果有函数属性值,则使用自己写的deepClone
方法。