详细讲解js中的深拷贝与浅拷贝

article/2025/10/12 4:14:02

1 概述

深拷贝与浅拷贝在其它语言中也经常被提及到,在实际项目开发过程中也常常需要区分当前使用的到底是深拷贝还是浅拷贝,有时候在该使用深拷贝的地方,我们使用了浅拷贝,会导致深藏不露的bug。

2 数据类型

在探讨深浅拷贝之前,我们先梳理一下js中的数据类型,js的数据类型分为两类:基本数据类型和引用数据类型,前者是存储在栈内存中,后者是将其地址存在栈内存中,而真实数据存储在堆内存中
如下图所示,基本类型如number、string、boolean、Null和undefined等存储在栈内存中,而引用数据类型如Array、Object和函数等则是分别存储数据1的地址、数据2的地址和数据3的地址。
栈内存与堆内存

3 深浅拷贝

3.1 拷贝对象为基本数据类型

js中的基本数据类型:String Number Boolean Null Undefined,在赋值的过程中都是深拷贝。
例如,let a = 10 ; b = a , 修改其中一个变量的值,不会影响到另一个变量的值。

3.2 拷贝对象中有引用数据类型

浅拷贝:会在栈中开辟另一块空间,并将被拷贝对象的栈内存数据完全拷贝到该块空间中,即基本数据类型的值会被完全拷贝,而引用类型的值则是拷贝了“指向堆内存的地址”。
深拷贝:不仅会在栈中开辟另一块空间,若被拷贝对象中有引用类型,则还会在堆内存中开辟另一块空间存储引用类型的真实数据。

深浅拷贝的示意图如下图:
在这里插入图片描述

浅拷贝是拷贝一层,属性为对象时,浅拷贝是复制,两个对象指向同一个地址
深拷贝是递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址

4、js中的深浅拷贝

4.1 浅拷贝

4.1.1 slice()

    <script>let arr1 = [1, 42, [3, 4]]let arr1Copy = arr1.slice()arr1Copy[0] = 10arr1Copy[2][0] = 100console.log(arr1) // [1, 42, [100, 4]]console.log(arr1Copy) // [10, 42, [100, 4]]</script>

arr1中的元素1是基本数据类型,所以arr1Copy能够改变其值,而不影响arr1的值。
而[3, 4]是引用数据类型,arr1和arr1Copy指向同一块堆内存地址,所以这两个变量中3都变成了100。

4.1.2 concat()

 let arr2 = ['cat', 'dog', 'pig', {'name': 'xia', 'age': 18}]let arr2Copy = [].concat(arr2)arr2Copy[2] = 'big pig'arr2Copy[3]['name'] = 'aa'console.log(arr2)console.log(arr2Copy)

执行结果如下:
执行结果
类似的还有…扩展运算符、Array.from、Object.assign()方法。

4.2 深拷贝

4.2.1 JSON.parse(JSON.stringify(obj))

万能转换器 JSON.parse(JSON.stringify(obj))深拷贝已有对象,它可以深拷贝多层级的,不用担心嵌套问题。

  • JSON.stringfy() 将对象序列化成json对象
  • JSON.parse() 反序列化——将json对象反序列化成js对象

JSON.stingify(obj)将js中的对象转换成JSON字符串

 let jack = {name: 'jack'}console.log(jack)console.log(JSON.stringify(jack))

它们在格式上有区别。下图中的第一个是对象,name没有双引号括起来。第二个是json字符串,其中,name用双引号括起来了
在这里插入图片描述

JSON.parse()将json字符串解析成对象

 let obj = {name: '静茹秋叶'}console.log('obj: ', obj)console.log('json string: ', JSON.stringify(obj))let str = JSON.stringify(obj)console.log('--------------')console.log(str)console.log('str to obj: ', JSON.parse(str))

在这里插入图片描述
实际项目开发过程中,我使用的这种方式最多,除此之外,还可以使用

  • _.cloneDeep()
  • jQuery.extend()
  • 手写循环递归

5、Vue中的浅拷贝与深拷贝

两个button-counter共用同一个jack对象,用同一块地址,当其中一个实例改变时,会影响另一个实例的值。(浅拷贝)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>vue的data选项</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body><div id="app"><button-counter></button-counter><button-counter></button-counter></div><script>let jack = {counter: 0}// 子组件Vue.component('button-counter', {data() {// 函数类型return jack},template: `<button @click="counter++">click {{counter}} times</button>`})let vm = new Vue({el: '#app' // mount到DOM上})</script>
</body>
</html>

采用深拷贝,重新创建一块内存。这样,vue的button-counter组件中的counter值互不影响。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>vue的data选项</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body><div id="app"><button-counter></button-counter><button-counter></button-counter></div><script>let jack = {counter: 0}// 子组件Vue.component('button-counter', {data() {// 函数类型return JSON.parse(JSON.stringify(jack))},template: `<button @click="counter++">click {{counter}} times</button>`})let vm = new Vue({el: '#app' // mount到DOM上})</script>
</body>
</html>

(例子来源于《Vue.js从入门到项目实战》书籍)


参考资料:

  1. https://vue3js.cn/interview/JavaScript/copy.html#
  2. https://github.com/wesbos/JavaScript30
  3. 《Vue.js从入门到项目实战》书籍
    最后特别感谢评论区的小伙伴,感谢他们指出了我的问题。

http://chatgpt.dhexx.cn/article/vPC3O20c.shtml

相关文章

js中的浅拷贝与深拷贝

在前端开发中的过程中我们经常要接触到浅拷贝与深拷贝的问题&#xff0c; 下面就对浅拷贝与深拷贝的概念、区别以及其有哪种实现方法来做一个简单的说明。 概念 浅拷贝&#xff1a; 浅拷贝是指&#xff0c;一个新的对象对原始对象的属性值进行精确地拷贝&#xff0c;如果拷贝…

JS之深拷贝与浅拷贝

一、理解 深拷贝 与 浅拷贝 针对于 引用类型(Object,Array,Function) 来说的 浅拷贝&#xff1a;在栈中分配一块新内存&#xff0c;拷贝需要拷贝的值&#xff0c; 对简单数据类型&#xff0c;就是拷贝值&#xff1b;对复杂数据类型&#xff0c;就是拷贝了一份栈内存储的堆内存…

lua踩坑之浅拷贝与深拷贝

文章目录 一、前言二、浅拷贝和深拷贝三、浅拷贝1.拷贝对象为string、number、boolean等基础类型时2.拷贝对象的类型为table类型时 三、深拷贝 一、前言 先来说说&#xff0c;为什么突然谈及到浅拷贝和深拷贝这个问题。因为时间紧任务重&#xff0c;lua零基础参与项目研发&…

解决浅拷贝的五种方式

浅拷贝和深拷贝以及值类型、引用类型概念理解请移步 认识javascript值类型&#xff0c;引用类型及浅拷贝与深拷贝的关系小白gis每周更新与WebGIS设计相关的文章教程&#xff0c;通过在线示例以及demo的方式&#xff0c;介绍Arcgis API、开源gis API的使用方法&#xff0c;帮助学…

iOS-深拷贝和浅拷贝

一、深拷贝(Deep Copy) 和 浅拷贝(Shallow Copy) 1、深拷贝&#xff08;Deep Copy&#xff09;&#xff1a;内容拷贝&#xff0c;拷贝数据到一块新内存区域&#xff0c;指针指向拷贝的数据区 &#xff08;另外创造一个一模一样的对象&#xff0c;新对象跟原对象不共享内存&am…

实现浅拷贝

浅拷贝是指&#xff0c;一个新的对象对原始对象的属性值进行精确地拷贝&#xff0c;如果拷贝的是基本数据类型&#xff0c;拷贝的就是基本数据类型的值&#xff0c;如果是引用数据类型&#xff0c;拷贝的就是内存地址。如果其中一个对象的引用内存地址发生改变&#xff0c;另一…

浅拷贝

图片转自js 深拷贝 vs 浅拷贝 我们平常说的深拷贝和浅拷贝都是基于对诸如 Object 和 Array 等引用数据类型的拷贝。对于基本数据而言&#xff0c;拷贝为某个值的赋值。 在说拷贝之前&#xff0c;我们先复习一下什么是基本数据类型和引用类型。 基本数据类型 JavaScript 中基…

深浅拷贝以及解决浅拷贝(以string浅拷贝为例)

一、什么是浅拷贝 在类和对象的时候&#xff0c;其中编译器生成的默认拷贝构造函数中&#xff0c;内置类型是按照字节方式直接拷贝的&#xff0c;而自定义类型是调用其拷贝构造函数完成拷贝的。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝&#xff0c;这种拷贝叫做浅…

ctf之培根密码

根据特征怀疑是培根密码 flag{AAAABAAAAAAAABAABBBAABBABABAAABAABAAAABBAABAAABABBABAAAAAABAABAAAABBBABABAABAABA} 直接在线解密 https://tool.bugku.com/peigen/ flag{BACONISDELICIOUS}

培根密码加解密

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01; 0x00 介绍 培根密码实际上就是一种替换密…

培根密码解密脚本

官方吐槽&#xff1a;疫情复发难受&#xff0c;什么时候是个头 #!/usr/bin/env python3 # -*- coding:utf-8 -*- #Author&#xff1a;later_future import string miweninput("请输入密文&#xff1a;") count0 msg"" flag"" #培根加密百度百科…

攻防世界crypto部分sherlock的writeup,原来不是培根密码。

下载附件后&#xff0c;发现是一个很大的文本&#xff0c;搜了下flag没啥收获。 1、后来看到下面这个 2、明显的故意大写&#xff0c;难道是培根密码&#xff1f;这就有思路了&#xff0c;将大写过滤出来&#xff1a; cat f590c0f99c014b01a5ab8b611b46c57c.txt | grep -Eo […

培根密码加解密(Python)

原理 加密时&#xff0c;明文中的每个字母会根据下面转换成5个字母&#xff1b; 解密时&#xff0c;密文中的每5个字母为一组转换成对应的1个字母&#xff1b; Python代码如下&#xff1a; CODE_TABLE { #培根字典aaaaa:a,aaaab:b,aaaba:c,aaabb:d,aabaa:e,aabab:f,aabba:…

CTF密码学-加解密总结

零基础学黑客&#xff0c;搜索公众号&#xff1a;白帽子左一密码学基本简介 密码学&#xff08;在西欧语文中&#xff0c;源于希腊语krypts“隐藏的”&#xff0c;和grphein“书写”&#xff09;是研究如何隐密地传递信息的学科。 在现代特别指对信息以及其传输的数学性研究&…

密码及编码

1. 密码 古典密码学 凯撒密码(Caeser)&#xff1a;位移密码 特殊形式&#xff08;加解密相同&#xff0c;因为26个字母是循环的&#xff09;&#xff1a;ROT13 栅栏密码&#xff1a;分组密码。 弗吉尼亚 现代密码学 对称加密算法&#xff1a;使用加密用过的秘钥及相同算法的…

CTF-密码学-培根密码

题目&#xff1a;bacon bAcon iS a MEaT prodUcT prePared frOm a pig and UsuALLy cUReD. 读题&#xff1a;翻译过来意思是培根 审题&#xff1a;联想到培根密码 解题&#xff1a;培根密码就是大写变A小写变B import string timu"bAcon iS a MEaT prodUcT prePared frOm…

【无标题】简单的培根密码解密

第一题 题目AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAAAABB 此题由大写字母AB组成&#xff0c;不难看出这可以用培根密码转换器进行解密得出flag 解密得出flag&#xff5b;HELLO WORD&#xff5d;

CTF-Show密码学【摩斯码、培根密码】

萌新 密码33 一、题目信息 题目名称&#xff1a;我想吃培根题目描述&#xff1a;-- — .-. … . …–.- … … …–.- -.-. — — .-… …–.- -… …- - …–.- -… .- -.-. — -. …–.- … … …–.- -.-. — — .-… . .-. …–.- – – -… -… – -… – -… – – – -…

CTF-培根密码

CTF学习上的一些疑点和解疑 主题&#xff1a;培根密码的随意性 反正我是觉得挺离谱的 序章 CTF学习上的一些疑点和解疑前言&#xff1a;培根小贴士一、培根密码是什么&#xff1f;二、解答1.题目2.解密顺序 总结还没听懂的我给大家展现一些例子&#xff1a; 前言&#xff1a;…

密码学笔记——培根密码

培根密码,培根所用的密码是一种本质上用二进制数设计的,没有用通常的0和1来表示,而是采用a和b 一、培根密码加密方式 第一种方式: A aaaaa B aaaab C aaaba D aaabb E aabaa F aabab G aabba H aabbb I abaaa J abaab K ababa L ababb M abbaa N abbab O abbba P abb…