深拷贝和浅拷贝的区别及应用场景详解

标题:深拷贝和浅拷贝的区别及应用场景详解

引言

在前端开发中,深拷贝和浅拷贝是处理对象和数组复制时常用的两种方式。它们的实现和应用场景有着明显的区别,对于开发者来说了解这些区别是非常重要的。本文将详细解释深拷贝和浅拷贝的概念,并提供它们在不同场景中的应用示例。

浅拷贝

浅拷贝定义

浅拷贝是指创建一个新的对象或数组,并复制原始对象或数组的值。它们可能共享一些内部数据,但并不共享相同的内存地址。当对新对象或数组进行修改时,不会影响原始对象或数组的值。

浅拷贝的实现方式:

  • 对象:使用Object.assign()、扩展操作符{...}等等。
  • 数组:使用Array.slice()Array.concat()、扩展操作符[...]等等。

例子:

对象拷贝

  • 使用Object.assign()方法进行浅拷贝:
js 复制代码
const originalObj = {
  name: "John",
  age: 25
};

const copyObj = Object.assign({}, originalObj);

copyObj.age = 30;

console.log(originalObj.age);  // 输出: 25
console.log(copyObj.age);  // 输出: 30
  • 使用扩展运算符({...})进行浅拷贝:
js 复制代码
const originalObj = {
  name: "John",
  age: 25
};

const copyObj = { ...originalObj };

copyObj.age = 30;

console.log(originalObj.age);  // 输出: 25
console.log(copyObj.age);  // 输出: 30

数组的浅拷贝

  • 使用Array.slice()方法进行浅拷贝:
js 复制代码
const originalArr = [1, 2, 3];
const copyArr = originalArr.slice();

copyArr[0] = 10;

console.log(originalArr);  // 输出: [1, 2, 3]
console.log(copyArr);  // 输出: [10, 2, 3]
  • 使用Array.concat()方法进行浅拷贝:
js 复制代码
const originalArr = [1, 2, 3];
const copyArr = originalArr.concat();

copyArr[0] = 10;

console.log(originalArr);  // 输出: [1, 2, 3]
console.log(copyArr);  // 输出: [10, 2, 3]
  • 使用扩展运算符([...])进行浅拷贝:
js 复制代码
const originalArr = [1, 2, 3];
const copyArr = [...originalArr];

copyArr[0] = 10;

console.log(originalArr);  // 输出: [1, 2, 3]
console.log(copyArr);  // 输出: [10, 2, 3]

浅拷贝的应用场景

  • 浅拷贝适用于复制简单对象,(简单对象指的是对象的属性或数组的元素是原始类型的数据,如字符串、数字、布尔值等。这些原始类型的数据在内存中是独立存储的,并不会相互影响)并且在部分属性修改或只读副本等场景中使用。当涉及到复杂结构或需要递归复制对象的情况时,深拷贝更常用。

注意点

  • 对于包含嵌套对象或数组的复杂结构,浅拷贝只复制了内部对象的引用,而没有对其进行递归复制。在这种情况下,深拷贝更适合确保复制所有嵌套对象和数组的内容,以避免原始对象的更改。

深拷贝

深拷贝定义

深拷贝是指创建一个新的对象或数组,并递归地复制原始对象或数组的所有嵌套对象和数组。新对象或数组是完全独立的,与原始对象或数组没有任何关联,对新对象或数组的修改不会影响原始对象或数组。

深拷贝的实现方式

  • 对象和数组:使用JSON.parse(JSON.stringify())方法对对象或数组进行序列化和反序列化。(序列化是将对象或数组转换为字符串的过程,而反序列化则是将字符串转换回对象或数组的过程。通过将对象或数组序列化为字符串,再通过解析字符串来创建新的对象或数组,可以实现深拷贝
js 复制代码
const originalObj = {
  name: "John",
  age: 25,
  hobbies: ["抽烟", "喝酒", "烫头"],
  address: {
    city: "北京",
    country: "中国",
    coordinates: {
      latitude: 39.9042,
      longitude: 116.4074
    }
  }
};

const copyObj = JSON.parse(JSON.stringify(originalObj));

copyObj.age = 30;
copyObj.hobbies.push("吹牛");
copyObj.address.city = "上海";
copyObj.address.coordinates.latitude = 31.2304;  // 将纬度改上海的坐标
copyObj.address.coordinates.longitude = 121.4737;  // 将经度改上海的坐标

console.log(originalObj.age);  // 输出: 25
console.log(originalObj.hobbies);  // 输出: ["抽烟", "喝酒", "烫头"]
console.log(originalObj.address.city);  // 输出: "北京"
console.log(originalObj.address.coordinates.latitude);  // 输出: 39.9042
console.log(originalObj.address.coordinates.longitude);  // 输出: 116.4074

console.log(copyObj.age);  // 输出: 30
console.log(copyObj.hobbies);  // 输出: ["抽烟", "喝酒", "烫头","吹牛"]
console.log(copyObj.address.city);  // 输出: "上海"
console.log(copyObj.address.coordinates.latitude);  // 输出: 31.2304
console.log(copyObj.address.coordinates.longitude);  // 输出: 121.4737

梳理

  • 原始对象originalObj包含了三层嵌套的结构。我们通过使用JSON.stringify()将其转化为字符串,再使用JSON.parse()将其转化为新的深拷贝对象copyObj。然后,我们对copyObj进行了一系列修改,包括修改age属性的值、向hobbies数组中添加新的元素、修改address对象中的city属性的值,以及修改coordinates对象中的latitude属性的值。这些修改不会影响原始对象originalObj的值。

JSON.parse(JSON.stringify())方法注意点

  • 通过JSON.parse(JSON.stringify())方法可以实现对三层嵌套对象或数组的深拷贝。请记住,这种方法可能会导致数据类型的变化,比如日期对象会转换为字符串。并且对于大型或复杂的对象,性能可能会受到影响。

深拷贝的应用场景

  • 适用于复制复杂对象或数组,其中对象的属性或数组的元素也是对象或数组,或不希望修改副本后影响原始对象或数组。

注意点

  • 在某些情况下,深拷贝可能会存在限制或问题,如循环引用或函数的拷贝,因此需要根据具体情况进行评估和选择使用深拷贝或浅拷贝。

结论

深拷贝和浅拷贝在JavaScript开发中有着不同的应用场景和实现方式。了解它们的区别对于正确处理对象和数组的复制至关重要。开发者应根据实际需求来选择适合的拷贝方式,以确保代码的正确性和可维护性。

相关推荐
小爱丨同学36 分钟前
宏队列和微队列
前端·javascript
沉登c1 小时前
Javascript客户端时间与服务器时间
服务器·javascript
持久的棒棒君1 小时前
ElementUI 2.x 输入框回车后在调用接口进行远程搜索功能
前端·javascript·elementui
小程xy4 小时前
react 知识点汇总(非常全面)
前端·javascript·react.js
非著名架构师5 小时前
js混淆的方式方法
开发语言·javascript·ecmascript
多多米10056 小时前
初学Vue(2)
前端·javascript·vue.js
敏编程6 小时前
网页前端开发之Javascript入门篇(5/9):函数
开发语言·javascript
看到请催我学习6 小时前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
XiaoYu20028 小时前
22.JS高级-ES6之Symbol类型与Set、Map数据结构
前端·javascript·代码规范
儒雅的烤地瓜8 小时前
JS | JS中判断数组的6种方法,你知道几个?
javascript·instanceof·判断数组·数组方法·isarray·isprototypeof