5.4 Javascript中的浅拷贝与深拷贝

目录

一、Javascript中的浅拷贝与深拷贝概述

JavaScript 中的浅拷贝和深拷贝是常见的两种对象复制方式,它们分别从不同的角度来复制对象的属性和方法。

1. 浅拷贝(Shallow Copy)

浅拷贝会创建一个新的对象,然后将原始对象中的所有属性和方法都复制到新的对象中。但是,如果原始对象中有一些属性的值是对象或数组,那么浅拷贝只会复制它们的引用,而不是复制实际的对象或数组。因此,如果在浅拷贝后修改了原始对象中的这些属性,那么新对象中的对应属性也会被修改。

示例代码:

let obj1 = { name: 'John', age: 26, hobbies: ['reading', 'music'] };

let obj2 = Object.assign({}, obj1);

obj1.name = 'Tom';

obj1.hobbies.push('sports');

console.log(obj1); 
// { name: 'Tom', age: 26, hobbies: ['reading', 'music', 'sports'] }

console.log(obj2); 
// { name: 'John', age: 26, hobbies: ['reading', 'music', 'sports'] }

上述代码中,先创建了一个包含 name、age 和 hobbies 属性的对象 obj1,hobbies 属性的值是一个包含两个元素的数组。然后使用 Object.assign 方法将 obj1 的所有属性都复制到一个新的对象 obj2 中。接下来,修改 obj1 的 name 和 hobbies 属性,并将一个新的元素添加到 hobbies 数组中,结果显示出 obj1 和 obj2 的区别。

2. 深拷贝(Deep Copy)

深拷贝也会创建一个新的对象,并将原始对象中所有属性和方法都复制到新的对象中。但是,与浅拷贝不同的是,深拷贝会复制所有的嵌套属性和数组,而不仅仅是它们的引用。因此,在深拷贝后,新对象和原始对象中的所有属性和方法都是完全独立的,修改一个对象不会影响另一个对象。

示例代码:

let obj1 = { name: 'John', age: 26, hobbies: ['reading', 'music'] };

let obj2 = JSON.parse(JSON.stringify(obj1));

obj1.name = 'Tom';

obj1.hobbies.push('sports');

console.log(obj1);
// { name: 'Tom', age: 26, hobbies: ['reading', 'music', 'sports'] }

console.log(obj2);
// { name: 'John', age: 26, hobbies: ['reading', 'music'] }

上述代码中,实现深拷贝的方法是使用 JSON.stringify 和 JSON.parse 来序列化和反序列化对象。先创建一个包含 name、age 和 hobbies 属性的对象 obj1,hobbies 属性的值是一个包含两个元素的数组。然后使用 JSON.stringify 将 obj1 序列化为一个字符串,接着使用 JSON.parse 将这个字符串反序列化为一个新的对象 obj2。接下来,修改 obj1 的 name 和 hobbies 属性,并将一个新的元素添加到 hobbies 数组中,结果显示出 obj1 和 obj2 的区别。

二、Javascript中的浅拷贝与深拷贝概述

JavaScript 中的浅拷贝和深拷贝可以通过多种方式实现。

1. 浅拷贝(Shallow Copy)

a. 使用数组的浅拷贝
const arr1 = [1, 2, 3];  

const arr2 = arr1.slice(); // 浅拷贝

b. 使用对象的浅拷贝
const obj1 = { a: 1, b: 2 };  

const obj2 = obj1; // 浅拷贝

c. 使用ES6的扩展运算符 … 和赋值操作符
const obj1 = { a: 1, b: 2 };  
const obj2 = [...obj1]; // 浅拷贝  
  
const arr1 = [1, 2, 3];  
const arr2 = [...arr1]; // 浅拷贝

d. 使用Object.assign()方法
const arr1 = [1, 2, 3];  

const arr2 = [...arr1]; // 浅拷贝

2. 深拷贝(Deep Copy)

a. 递归拷贝每一个属性
deepCopy: function(obj) {  
   // 判断是否为 null、undefined 或空对象  
   if (obj === null || obj === undefined || obj.nodeType === null) {  
     return obj;  
   }  
   
   // 如果是对象,则递归拷贝每一个属性  
   if (Array.isArray(obj)) {  
     return [...obj];  
   }  
   
   // 如果是数组,则递归拷贝每一个元素  
   if (Array.isArray(obj[0])) {  
     return [...obj[0]];  
   }  
   
   // 如果是字符串,则递归拷贝每一个字符  
   if (typeof obj === 'string') {  
     return JSON.parse(JSON.stringify(obj));  
   }  
   
   // 如果是 Date 对象,则递归拷贝每一个日期部分  
   if (typeof obj === 'object' && obj.constructor === Date) {  
     return new Date(...obj.getTime());  
   }  
   
   return obj;  
}

let myObj = { a: { b: { c: 'Hello' }, d: true }, e: [1, 2, 3], f: 123 };  

console.log('Deep Copy:', this.deepCopy(myObj));

b. 使用 JSON.parse 和 JSON.stringify
let obj1 = { a: 1, b: { c: 2 } };

let obj2 = JSON.parse(JSON.stringify(obj1));

但是要注意,使用 JSON.stringify 和 JSON.parse 可能存在一些问题,例如一些特殊的数据类型,如 RegExp、Function、Date 等,在序列化和反序列化时可能会失效。

c. 使用第三方库,如 Lodash、Immutable 等。
let obj1 = { a: 1, b: { c: 2 } };

let obj2 = _.cloneDeep(obj1); // 使用 Lodash

let obj3 = Immutable.Map(obj1); // 使用 Immutable

三、Javascript中的浅拷贝与深拷贝优缺点对比

1. 浅拷贝(Shallow Copy)

浅拷贝,即只复制一层对象属性,而不复制属性值所指向的对象。

浅拷贝的优点是:
	1.简洁易懂,实现起来比较容易;
	2.复制的对象是原对象的一份浅表副本,对副本的修改不会影响原对象。

浅拷贝的缺点是:
	它只复制对象的一层,如果对象的属性值是一个引用类型,那么只会复制这个属性值的引用,而不是复制整个引用类型的对象。
	这就意味着,对浅拷贝后的对象进行修改,很可能会改变原对象。这种缺点在多层嵌套的对象中会更加明显。

2. 深拷贝(Deep Copy)

深拷贝,会完全复制整个对象,包括对象中的所有嵌套属性,这样就避免了浅拷贝中的缺点。

深拷贝的优点是:
	1. 完全复制了整个对象,对副本的修改不会影响原对象;
	2. 不受对象层次结构的限制,可以复制多层嵌套的对象。

深拷贝的缺点是:
	深拷贝的实现通常比浅拷贝复杂得多,而且会消耗更多的计算资源。对于大型对象或多层嵌套的对象,深拷贝的效率和性能可能会变得很低。

因此,在实际开发中,需要根据具体情况选择浅拷贝还是深拷贝。如果原对象中没有多层嵌套的对象,或者只需要复制对象的一层属性,那么可以使用浅拷贝;如果需要完全复制整个对象,那么可以使用深拷贝。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ibun.song

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值