Javascript进阶篇:深拷贝实现的四种方式
在Javascript中,数据类型可以分为原始类型和引用类型。其中,原始类型在赋值、作为函数参数、返回值传递等情况下,直接进行值的传递。而引用类型则是传递引用地址。这样一来,在同一个作用域下、赋值、作为函数参数、返回值传递等情况下,多个变量可能会指向同一引用地址的内存空间,导致某些问题。为了避免这种问题,我们需要对引用类型进行深拷贝。
本文将介绍四种Javascript实现深拷贝的方式:
方式一:JSON.parse(JSON.stringify(obj))
利用JSON.stringify可以把JSON对象转换为字符串,JSON.parse方法可以把字符串转换为对象的特性,可以达到深拷贝的效果。
let obj = {a: 1, b: {c: 2}};
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false
但也有需要注意的点,比如:
- undefined无法被序列化,所以在原对象中该属性会被忽略;
- NaN、Infinity和-Infinity会被转化为null;
- Date日期对象也无法被序列化(Javascript中日期对象都有一个toString方法,因此JSON.stringify调用Date对象时会把日期转换成字符串);
- 对象中函数属性会被忽略掉;
- 对象中RegExp、Error对象等特殊对象无法被序列化;
- 如果obj对象中存在循环引用的情况也无法正确实现深拷贝。
方式二:递归遍历对象拷贝
递归遍历对象,对于每一个属性进行递归操作,从而实现深拷贝。
function deepClone(obj) {
let newObj = obj instanceof Array ? [] : {};
for(let i in obj){
if (typeof obj[i] === 'object') {
newObj[i] = deepClone(obj[i]);
} else {
newObj[i] = obj[i];
}
}
return newObj;
}
let obj = {a: 1, b: {c: 2}};
let newObj = deepClone(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false
需要注意的是,递归深拷贝也需要注意循环引用的问题。
方式三:利用Object.assign
Object.assign方法可以使用多个源对象中的属性和方法拷贝到一个目标对象中去。利用这个特性,我们也可以实现深拷贝。
function deepClone(obj) {
let newObj = obj instanceof Array ? [] : {};
if (typeof obj !== 'object') {
return obj;
}
for(let i in obj){
if (typeof obj[i] === 'object') {
newObj[i] = deepClone(obj[i]);
} else {
newObj[i] = obj[i];
}
}
let temp = Object.assign({}, obj, newObj);
return temp;
}
let obj = {a: 1, b: {c: 2}};
let newObj = deepClone(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false
与上一个方法类似,也需要注意循环引用的问题。
方式四:使用第三方库
使用第三方库中的深拷贝方法,如lodash中的_.cloneDeep方法。这个方法可以深度克隆一个对象,包括原型链。
let obj = {a: 1, b: {c: 2}};
let newObj = _.cloneDeep(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false
需要注意的是,使用第三方库虽然方便,但是也会增加代码依赖和体积。
总结
以上四种Javascript实现深拷贝的方式,各有利弊。在具体项目中,我们需要根据实际情况进行选择。需要注意的是,在实现深拷贝时,需要考虑到循环引用、特殊对象等特殊情况,以避免影响程序的正常运行。
两条示例:
- 示例一:使用JSON.parse(JSON.stringify(obj))进行深拷贝
let obj = {a: 1, b: {c: 2}};
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false
- 示例二:使用第三方库lodash的深拷贝方式
let obj = {a: 1, b: {c: 2}};
let newObj = _.cloneDeep(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:javascript进阶篇深拷贝实现的四种方式 - Python技术站