浅谈深浅拷贝

浅谈深浅拷贝今天突然接到某巴的面试电话 和面试官聊了半个小时 问了我深浅拷贝 promise vue 和 react 的数据绑定 element 的实现原理 以后的规划等等 当时回答的深浅拷贝被我说反了 苦笑 虽然复习的时候看过 但是没有完全的理解 所以趁热打铁 赶紧学习总结下 一 JS 的数据类型要想学习深浅拷贝 首先需要了解 在 javascript 中有两种数据类型 分别是基本数据类型 Number

 一、JS的数据类型

要想学习深浅拷贝,首先需要了解javascript的数据类型

javascript 中有两种数据类型,分别是基本数据类型(Number、String、Undefined、Boolean、Null、Symbol)和引用数据类型(对象、数组、函数)。

基本数据类型是按值访问的,操作的就是变量保存的;如果是引用类型,则是通过保存在变量中的引用类型的地址来操作实际对象。

基本类型是不可变的,任何方法都无法改变一个基本类型的值,也不可以给基本类型添加属性或者方法。但是可以为引用类型添加属性和方法,也可以删除其属性和方法。

下面请看示例:

let num1 = 10; let obj1 = { name: "ding" } let num2 = num1; let obj2 = obj1; num2 = 20; obj2.name = "bai"; console.log(num1); // 10 console.log(obj1.name); // bai

可以看出赋值的时候,基本类型是在栈内存中重新开辟内存,存放变量num2,所以在栈内存中存放的基本数据类型是不会相互影响的。引用类型复制的只是引用地址,指向的是堆内存中同一地址的同一对象,修改时会相互影响。

所以对于基本类型的拷贝,并没有深浅拷贝的区别,我们所说的深浅拷贝都是对于引用类型而言的。

二、浅拷贝

浅拷贝的意思就是只复制引用,而未复制真正的值,源对象和目标对象共享同一块内存,一个修改时另一个也跟着修改。上述代码就是利用 = 赋值操作实现的浅拷贝。也可以利用Object.assign或展开运算符 ... 来实现浅拷贝。

通过 Object.assign 实现,Object.assign第一级属性深拷贝,以后级别属性浅拷贝。

let a = { age: 1, name: { asd: "123" } }; let b = Object.assign({}, a); b.age = 2; b.name.asd = "456"; console.log(a.age, a.name.asd); //1 ‘456’

 通过展开运算符 ... 来实现深拷贝,但是需要注意的是只针对对象的第一级属性有效

var arr = { name: "aaa", other: { name: "bbb" } }; var arr2 = { ...arr }; arr2.name = "AAA"; arr2.other.name = "BBB"; console.log(arr); // { name: 'aaa', other: { name: 'BBB' } } console.log(arr2); // { name: 'AAA', other: { name: 'BBB' } }

三、深拷贝

深拷贝实现的是真正意义上的对象的拷贝。深拷贝会创造一个一模一样的对象,其内容地址是自助分配的,拷贝结束之后,内存中的值完全相同,但是内存地址是不一样的,目标对象跟源对象不共享内存,修改任何一方的值,不会对另外一方造成影响。

可以通过JSON.parse(JSON.stringify(object))实现深拷贝:

var arr = { name: "aaa", other: { name: "bbb" } }; var arr2 = JSON.parse(JSON.stringify(arr)); arr2.name = "AAA"; arr2.other.name = "BBB"; console.log(arr); // { name: 'aaa', other: { name: 'bbb' } } console.log(arr2); // { name: 'AAA', other: { name: 'BBB' } }

实现原理:拷贝一个字符串会开辟一个新的存储地址,这样就切断了引用对象的指针联系,所以先转成一个字符串,在解析出对象,这样就可以深拷贝一个对象 。

补充:

JSON.parse(str) 用于从一个字符串中解析出 json 对象,JSON.stringify(obj)用于从一个对象解析出字符串。

自己实现一个深拷贝函数:

function deepClone(obj) { let res; if (typeof obj === 'object') { if (obj === null) { res = obj; } else { res = Array.isArray(obj) ? [] : {}; for (let key in obj) { let val = obj[key]; res[key] = deepClone(val); } } } else { // 除了数组和对象之外的类型 res = obj; } return res; }

验证:

let obj = { a: { name: '小明' }, b: 111, c: [1,2,3,4], d: '你好', e: null, f: function() {} }; let b = deepClone(obj); obj.a.name = 222; console.log(obj,b);

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212962.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午6:52
下一篇 2026年3月18日 下午6:52


相关推荐

  • unbuntu安装google浏览器和谷歌浏览器驱动

    unbuntu安装google浏览器和谷歌浏览器驱动1、安装google浏览器sudowgethttp://www.linuxidc.com/files/repo/google-chrome.list-P/etc/apt/sources.list.d/wget-q-O-https://dl.google.com/linux/linux_signing_key.pub|sudoapt-keyadd-sudoapt-…

    2022年6月11日
    35
  • drupal安装教程mysql_Drupal8 安装教程

    drupal安装教程mysql_Drupal8 安装教程安装Drupal8需要环境环境:UNIX/Linux,OSX,或者windowsweb服务器:Apache2,nginx,MicrosoftIIS等数据库:推荐数据库Mysql(5.5.3),MariaDB(5.5.20),PerconaServer(5.5.8),支持:PostgreSql(9.1.2),SQLite(3.6.8)开始安装我的环境,OSX,Apache2,Mysql(…

    2022年6月6日
    41
  • 数据库备份之我见(精华)

    数据库备份之我见(精华)

    2021年7月25日
    75
  • java输入输出的方法

    java输入输出的方法java输入输出目录一、控制台输入输出二、文件读写一、控制台输入输出 java控制台的输入输出主要依赖于scanner类,使用Scannerscanner=newScanner(System.in)获取了控制台输入的字段,其中system.in就表示这个对象读取的是控制台。publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);while(sc

    2022年5月26日
    43
  • 775针最好的cpu有哪些_1156针cpu是几代

    775针最好的cpu有哪些_1156针cpu是几代针脚也就是cpu的接口,是cpu和主板的连接件,不同的针脚代表不同cpu的类型,现在775针cpu已经成为Intel桌面CPU的标准接口。今天就为大家简单介绍775针cpu以及它们同系列性能排行最好的一款吧。一、775针的cpu的有哪些?主要有奔腾4、赛扬D,奔腾D8、D9系列,奔腾E2、奔腾E5、E6,酷睿E4、E6、E7、E8,酷睿Q6、Q8、Q9。奔腾4采用LGA775接口的有5和6系列,经…

    2026年2月5日
    3
  • tabnine激活码(破解版激活)

    tabnine激活码(破解版激活),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月17日
    61

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号