理解JavaScript深浅拷贝以及方法
先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数****。
执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会造成内存泄漏问题!
这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。
所以,在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。
执行结果:调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。
总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
深拷贝方法:
-
使用
JSON.parse()
与JSON.stringify()
对对象进行拷贝通常情况下,我们可以使用
JSON.parse()
与JSON.stringify()
实现对象的深克隆,如下:var clone = function (obj) { return JSON.parse(JSON.stringify(obj)); } // 这种方法只适用于纯数据json对象的深度克隆,因为有些时候,这种方法也有缺陷
-
目前没有发现bug的对象深拷贝方法
var clone = function (obj) { if (obj === null) return null if (typeof obj !== 'object') return obj if (obj.constructor === Date) return new Date(obj) if (obj.constructor === RegExp) return new RegExp(obj) var newObj = new obj.constructor() //保持继承链 for (var key in obj) { if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性 var val = obj[key] newObj[key] = typeof val === 'object' ? arguments.callee(val) : val // 使用arguments.callee解除与函数名的耦合 } } return newObj }
-
展开运算符进行浅拷贝
var arr1=[1,2,5,6,4]; var arr2=[...arr1]; arr1 == arr2 // false; arr1.push(8,9,9) // (8)[1, 2, 5, 6, 4, 8, 9, 9] arr2 // (5) [1, 2, 5, 6, 4] var arr3 = arr1 arr3 // (8) [1, 2, 5, 6, 4, 8, 9, 9] arr1.push(12313,12313) // (10) [1, 2, 5, 6, 4, 8, 9, 9, 12313, 12313] arr3 // (10) [1, 2, 5, 6, 4, 8, 9, 9, 12313, 12313]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?