【JS】浅谈浅拷贝与深拷贝

浅拷贝与深拷贝

  • 前言
  • 一、浅拷贝?
    • 1.1是什么?
    • 1.2做什么?
    • 1.3为什么使用?
    • 1.4实现方式?
    • 1.5 应用场景?
  • 二、深拷贝?
    • 2.1是什么?
    • 2.2做什么?
    • 2.3为什么使用?
    • 2.4实现方式?
    • 2.5应用场景?
  • 三、区别
  • 总结


前言

我们对数组或者对象进行操作的时候,有时并不想操作原始对象,就会将对象或数组复制出新一份,在新的一份中进行操作。

深拷贝与浅拷贝是常用于对象或数组进行复制。
在这里插入图片描述


一、浅拷贝?

1.1是什么?

浅拷贝是指复制对象时,只复制对象的引用,而不复制引用指向的对象本身。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是引用类型,拷贝的就是内存中的地址。

先用一张图理解这句话
在这里插入图片描述
当B从A中复制一份时,他们在内存地址中指向仍旧是同一个,如果此时A改变了某些值,因为B和A指向是相同的,B此时也会跟着改变。也就是说B只是复制A在内存地址的引用,并没复制A的本身。

1.2做什么?

浅拷贝它复制了原始对象中的所有字段到新的对象中,对于值类型,复制操作不会对原对象的字段值有任何影响;

对于引用类型,新的对象对引用类型中的字段赋值等操作,会对原引用类型对象中的字段进行更改。

浅拷贝经常用于在不需要深度复制对象的情况下快速复制对象。

1.3为什么使用?

  • 内存使用优化:浅拷贝允许多个对象共享相同的数据区,这样可以显著减少内存的消耗。特别是当处理大型数据结构。
  • 性能提升:减少拷贝的次数,从而提升程序的运行效率。
  • 特定需求:只要复制对象的顶层数据,而不是对象的所有层次。

1.4实现方式?

  • 扩展运算符(…)
const originalArray = [1, 2, [3, 4]];  
const shallowCopyArray = [...originalArray]; 
  • Object.assign()
const originalArray = { a: 1, b: { c: 2 } };  
const shallowCopyArray = Object.assign({},originalArray); 
  • Array.prototype.slice(), Array.prototype.concat()
const originalArray = [1, 2, [3, 4]];  
const shallowCopyArray = originalArray.slice(); 

const shallowCopyArray = originalArray.concat(); 

1.5 应用场景?

  • 组件间传值:子组件只是读取这些数据而不进行修改
  • 计算属性或方法中的临时变量:基于当前组件的状态或传入的参数创建一些临时变量。如果这些临时变量只是简单地读取状态或参数的值,而不进行修改

二、深拷贝?

2.1是什么?

深拷贝是指复制对象时,不仅复制对象本身,还复制对象所引用的所有对象,直到所有引用的对象都被完全复制。

先用一张图理解这句话
在这里插入图片描述
当B从A中复制一份时,不仅新创建了B对象,还创造一块新的内存,此时B和A在内存中的指向不再是同一块。如果A改变了,B不会受影响。

2.2做什么?

深拷贝独立创建新的对象和开辟一块新的内存,对于值和引用类型,复制操作不会对原对象的字段值有任何影响;

深拷贝经常用于不影响原对象情况下复制新对象。深拷贝相对于浅拷贝来说,更加复杂耗时,但可以确保数据的安全性。

2.3为什么使用?

  • 避免数据冲突:使用深拷贝可以确保新对象与原始对象完全独立,对其中一个对象的修改不会影响另一个。
  • 确保数据完整:深拷贝可以复制对象的所有层级,从而确保整个对象的完整性。
  • 特定需求:不影响原始数据操作。

2.4实现方式?

  • JSON.stringify()
const obj2=JSON.parse(JSON.stringify(obj1));

但是这种方式存在弊端,会忽略undefined、symbol和函数

const obj = {
    name: 'A',
    name1: undefined,
    name3: function() {},
    name4:  Symbol('A')
}
const obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); // {name: "A"}
  • 循环递归
function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝
  if (typeof obj !== "object") return obj;
  // 是对象的话就要进行深拷贝
  if (hash.get(obj)) return hash.get(obj);
  let cloneObj = new obj.constructor();
  // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 实现一个递归拷贝
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}
  • _.cloneDeep()
const _ = require('lodash');
const obj = {
    a: 1,
};
const obj1 = _.cloneDeep(obj);

2.5应用场景?

  • 组件间数据传递:子组件对数据的修改不会影响到父组件或其他兄弟组件。

  • Vuex状态管理:在Vuex中,状态是响应式的,当状态改变时,视图也会自动更新。通过深拷贝,我们可以创建一个状态的独立副本,在组件内部进行修改,而不会触发全局状态的更新。

  • 避免直接修改props:需要基于props的数据进行修改,可以先使用深拷贝创建一个副本,然后在副本上进行修改。

三、区别

  • 共同点:
    • 都是复制数据
  • 不同点:
    • 浅拷贝是复制内存中的地址,拷贝前后的对象,因为引用类型共享了同一块内存,修改会相互影响。基本类型值不变,引用类型会改变
    • 深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址。基本类型和引用类型不改变

总结

  • 浅拷贝
    • 引用同一块内存,会影响原数据
    • 基本类型值不变,引用类型会改变
    • 实现方式:… , Object.assign() , slice(),concat()
  • 深拷贝
    • 新开辟内存,不影响原数据
    • 基本类型和引用类型不改变
    • 实现方式:循环递归 , JSON.stringify() , loadsh库中_.cloneDeep()
      在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/454308.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

成都产业园排名出炉!金牛区这个园区成数字产业聚集地

近日,成都产业园排名榜单正式发布,可以看出金牛区成数字产业聚集地,其中,备受瞩目的国际数字影像产业园荣登榜首。这一排名不仅彰显了国际数字影像产业园在数字产业领域的卓越表现,更凸显了成都作为西部重要城市在科技…

51单片机系列-单片机定时器

🌈个人主页:会编辑的果子君 💫个人格言:“成为自己未来的主人~” 软件延时的缺点 延时过程中,CPU时间被占用,无法进行其他任务,导致系统效率降低,延时时间越长,该缺点就越明显&…

HBuilder发行微信小程序

首先需要完善mainifest.json中的基本配置 这个需要组测dcloud才可以获取,注册后点击重新获取就可以。 然后发行前还需要完成dcloud的信息,这个他会给你网址 点击连接完成信息填写就可以了 然后就可以发行了。 发行成功后会自动跳转微信小程序&#xff…

day02vue学习

day02 一、今日学习目标 1.指令补充 指令修饰符v-bind对样式增强的操作v-model应用于其他表单元素 2.computed计算属性 基础语法计算属性vs方法计算属性的完整写法成绩案例 3.watch侦听器 基础写法完整写法 4.综合案例 (演示) 渲染 / 删除 / 修…

Flutter第四弹:Flutter图形渲染性能

目标: 1)Flutter图形渲染性能能够媲美原生? 2)Flutter性能优于React Native? 一、Flutter图形渲染原理 1.1 Flutter图形渲染原理 Flutter直接调用Skia。 Flutter不使用WebView,也不使用操作系统的原生控件,而是…

如何深度学习

信息爆炸时代,诞生了很多新的学习方式,非常轻松就能掌握知识,比如,每天听一本书,半个小时就能学习一本书的精华,比如订阅名家专栏或者课程,在不长的时间内内就能学到很多知识。 很多人认为这样…

jenkins 使用k8s插件连接k8s集群

jenkins 安装k8s 插件 配置k8s节点 填写k8s 配置信息 生成秘钥 在服务器上面 查看地址 Kubernetes 服务证书 key cat /root/..kube/config 查看秘钥 对秘钥进行base64 位 加密 echo "秘钥内容" | base64 -d -----BEGIN CERTIFICATE----- MIIDITCCAgmgAwIB…

【node】模块化与包(二)

1、模块化的基本概念 模块化是指解决一个复杂的问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。 (1)模块化的优点 遵循固定规则,把大文件拆分成对立并相互依赖…

【Axure高保真原型】下拉列表切换图表

今天和大家分享通过下拉列表动态切换统计图表的原型模板,我们可以通过下拉列表选择要显示的图表,包括柱状图、条形图、饼图、环形图、折线图、曲线图、面积图、阶梯图、雷达图;而且图表数据可以在左侧表格中动态维护,包括增加修改…

数码管的动态显示(二)

1.原理 这个十六进制是右边的dp为高位。 数码管的动态显示,在第一个计数周期显示个位,在第二个周期显示十位,在第三个周期显示百位由于人眼的视觉和数码管的特性,感觉就是显示了234,每个数码管的显示需要从输入的数据里…

科普编程中 宿主环境(host environment) 基础概念

我们来说说 宿主环境 首先 什么是宿主环境? 宿主环境 (host environment) 意思就是 程序运行所必须的依赖环境 安卓和IOS 系统 就是两种完全不同的宿主环境 总所周知 微信版的安卓App 在苹果中是无法运行的 所以说 Android 是安卓软件的宿主环境 离开了这个宿主环…

ECharts饼图图例消失踩的坑

在使用Echarts的饼图时,当时做法是在图例数小于8时显示全部的图例,在大于8的时候显示前8个图例。于是用了两种不同的方式处理。导致出现切换时间后图例不显示的情况。 错误过程: 在进行图例生成时采用了两种不同的方式: ①如果…

Linux内核编译(版本6.0以及版本v0.01)并用qemu驱动

系统环境: ubuntu-22.04.1-desktop-amd64 目标平台: x86 i386 内核版本: linux-6.0.1 linux-0.0.1 环境配置 修改root密码 sudo passwd 修改软件源(非必要) vmtools安装(实现win-linux软件互传) 安装一些必须的软件&…

代码随想录算法训练营第25天|216.组和总和三、17.电话号码的字母组合

目录 一、力扣216.组合总和三1.1 题目1.2 思路1.3 代码 二、力扣17.电话号码的字母组合2.1 题目2.2 思路2.3 代码 一、力扣216.组合总和三 1.1 题目 1.2 思路 自己的想法:和总和问题思路类似,回溯法。 (1)k个数的组合&#xff0…

如何查看mnist数据集的图片

import numpy as np import matplotlib.pyplot as pltdef read_mnist_images(filename):with open(filename, rb) as f:# 读取魔术数字、图像数量、行数、列数magic_number int.from_bytes(f.read(4), big)number_of_images int.from_bytes(f.read(4), big)rows int.from_by…

《详解:鸿蒙NEXT开发核心技术》

我们现在都知道鸿蒙作为一个国产的全栈自研系统,经过国家主推后。已经引起人们很大的关注,其中作为开发者来说;许多一线大厂已经与其华为鸿蒙展开原生应用的合作了,目前了解到已经有200家。而之后出现了很多的高薪鸿蒙开发岗位&am…

ThreeJs 射线拾取不准确设置

欢迎关注进来点个关注; 关注获取更多咨询!关注获取答案! 1、效果图如下: 2、问题描述:点击一开始无法获取当前的位置,官方推荐直接使用 mouseClick.x = (event.offsetX / window.innderWidth) * 2 - 1; mouseClick.y = -(event.offsetY / window.innderHeight) * 2 + 1;…

独显直连是什么意思

很多小伙伴在购买笔记本电脑时,尤其是游戏本,都会看到详情页在介绍显卡提示有“独显直连”功能,那么独显直连是什么意思?它又有什么用呢? 独显直连是什么意思 独显直连,英文全称Graphics Processing Unit…

【你也能从零基础学会网站开发】Web建站之javascript入门篇 History对象与Location对象

🚀 个人主页 极客小俊 ✍🏻 作者简介:程序猿、设计师、技术分享 🐋 希望大家多多支持, 我们一起学习和进步! 🏅 欢迎评论 ❤️点赞💬评论 📂收藏 📂加关注 History历史对…

Linux本地搭建FastDFS系统

文章目录 前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Nginx1.9 配置Nginx 2. 局域网测试访问FastDFS3. 安装cpolar内网穿透4. 配置公网访问地址5. 固定公网地址5.…