JavaScript深拷贝原理与三种实现方式详解

作者:青柠

时间:2026-10-24

浏览:447

本文详细解析JavaScript中值类型与引用类型的内存存储机制,阐明浅拷贝仅复制指针而深拷贝完全克隆数据的区别。文章对比了JSON序列化、扩展运算符及手写递归函数三种深拷贝方案,分析各自在嵌套对象、函数及循环引用上的局限性,并提供完整的递归实现代码示例,帮助开发者根据场景选择最优拷贝策略。

文章目录

JavaScript深拷贝

在深入探讨深拷贝之前,首先需要理解JavaScript中数据的存储机制。

数据存储方式

理解值类型与引用类型的存储差异是掌握拷贝概念的基础。

JavaScript的数据类型主要分为两大类。

值类型包括:字符串(String)、数字 (Number)、布尔值 (Boolean)、空值(Null)、未定义(Undefined)以及符号(Symbol)。

值类型的数据存储在栈内存中,其数据大小是固定的,内存空间可以明确分配。

引用数据类型主要包括:对象(Object)、数组((Array)以及函数(Function)。

引用类型的数据存储在堆内存中,而栈内存中仅保存指向堆内存地址的指针。程序通过该指针访问堆内存中的实际数据。

存储结构示意图如下:

JavaScript深拷贝

什么是浅拷贝与深拷贝

明确了存储方式后,接下来讨论浅拷贝和深拷贝的概念。

拷贝(copy)类似于复制粘贴操作,下面通过具体示例进行说明。

当对值类型和引用类型分别进行赋值操作时,表现有所不同。


     var a = 5
     var b = a
     b += 5
     console.log('a=' + a,'b=' + b)
     var arr=[1,2,3]
     var brr=arr
     brr.push(10)
     console.log("arr为",arr)
     console.log("brr为",brr)

JavaScript深拷贝

现象:值类型的赋值互不影响,但引用类型(如数组)在修改副本时,原数组也会发生变化。

分析:浅拷贝仅针对引用类型,简单赋值仅复制指向堆内存的指针,导致原对象与副本共享同一数据。深拷贝则是完全复制引用类型的数据结构,而非仅仅复制地址指针。

浅拷贝原理示意图如下:

JavaScript深拷贝

常用的深拷贝实现方法

为了避免修改副本时影响原数据,对引用类型赋值时需采用深拷贝。

1. 使用JSON.stringify和JSON.parse

该方法可深拷贝数组和对象,支持嵌套结构,但无法处理函数。

缺点:无法拷贝对象中的方法(函数)。

使用方法示例:


     var brr=JSON.parse(JSON.stringify(arr))

具体代码示例:


  var arr = {
         name: '浪漫主义码农',
         age: 20,
         adress: ['jiangxi', 'changsha'],
         friends: {
             friend1: '张三',
             friend2: '李四'
         },
         function(){
             console.log("我是浪漫主义的对象")
         }
     }
     var brr=JSON.parse(JSON.stringify(arr))
     brr.name='法外狂徒张三'
     brr.adress[0]='长沙'
     console.log("arr为", arr)
     console.log("brr为", brr)

JavaScript深拷贝

2. 使用扩展运算符

利用对象的结构赋值特性实现。

缺点:无法对嵌套对象进行深拷贝,仅对第一层引用对象进行拷贝。

使用方法示例:


     var brr={...arr}

具体代码示例:


  var arr = {
         name: '浪漫主义码农',
         age: 20,
         adress: ['jiangxi', 'changsha'],
         friends: {
             friend1: '张三',
             friend2: '李四'
         },
         function(){
             console.log("我是浪漫主义的对象")
         }
     }
     var brr={...arr}
     brr.name='法外狂徒张三'
     brr.adress[0]='长沙'
     console.log("arr为", arr)
     console.log("brr为", brr)

JavaScript深拷贝

3. 手写递归深拷贝函数

此方法能完美解决上述问题。

函数定义示例:


  //使用递归实现深拷贝
     function deepClone(obj) {
         //判断拷贝的obj是对象还是数组
         var objClone = Array.isArray(obj) ? [] : {};
         if (obj && typeof obj === "object") { //obj不能为空,并且是对象或者是数组 因为null也是object
             for (key in obj) {
                 if (obj.hasOwnProperty(key)) {
                     if (obj[key] && typeof obj[key] === "object") { //obj里面属性值不为空并且还是对象,进行深度拷贝
                         objClone[key] = deepClone(obj[key]); //递归进行深度的拷贝
                     } else {
                         objClone[key] = obj[key]; //直接拷贝
                     }
                 }
             }
         }
         return objClone;
     }

具体调用示例:


      var arr = {
         name: '浪漫主义码农',
         age: 20,
         adress: ['jiangxi', 'changsha'],
         friends: {
             friend1: '张三',
             friend2: '李四'
         },
         fun: function(){
             console.log("我是" + this.name + "的对象")
         }
     }
     var brr = deepClone(arr)
     brr.name = '法外狂徒张三'
     brr.adress[0] = '长沙'
     console.log("arr为", arr)
     arr.fun()
     console.log("brr为", brr)
     brr.fun()
 ​
     //使用递归实现深拷贝
     function deepClone(obj) {
         //判断拷贝的obj是对象还是数组
         var objClone = Array.isArray(obj) ? [] : {};
         if (obj && typeof obj === "object") { //obj不能为空,并且是对象或者是数组 因为null也是object
             for (key in obj) {
                 if (obj.hasOwnProperty(key)) {
                     if (obj[key] && typeof obj[key] === "object") { //obj里面属性值不为空并且还是对象,进行深度拷贝
                         objClone[key] = deepClone(obj[key]); //递归进行深度的拷贝
                     } else {
                         objClone[key] = obj[key]; //直接拷贝
                     }
                 }
             }
         }
         return objClone;
     }

JavaScript深拷贝

总结

本文到此结束,希望能为读者提供帮助,欢迎关注本站获取更多技术内容。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章