深拷贝(deepclone)的原理和使用方法

一、什么是深拷贝

在javascript中,简单数据类型的赋值是直接传递值,而复杂数据类型则是传递地址。而深拷贝就是指在拷贝时会开辟新的内存地址存放数据,而不是对原地址直接引用。

举个例子,如果我们只是将一个对象赋值给另一个变量,那么这两个变量指向的是同一个地址,修改其中一个对象会影响到另一个对象,这就是浅拷贝:

var obj1 = {a: 1, b: 2};
var obj2 = obj1;
obj2.a = 3;
console.log(obj1.a); // 3

而如果我们进行深拷贝,如下所示:

var obj1 = {a: 1, b: 2};
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.a = 3;
console.log(obj1.a); // 1

这个时候,对象obj1的属性a并没有受到影响。

二、深拷贝的实现方式

1、递归实现深拷贝

深拷贝的实现方式有很多,其中一种比较常用的方式就是递归。

function clone(target){
    let result;
    if(typeof target === 'object'){
        if(Array.isArray(target)){
            result = [];
            for(let i in target){
                result.push(clone(target[i]));
            }
        }else if(target === null){
            result = null;
        }else if(target.constructor === RegExp){
            result = target;
        }else{
            result = {};
            for(let i in target){
                result[i] = clone(target[i]);
            }
        }
    }else{
        result = target;
    }
    return result;
}

递归的方式就是遍历对象和数组,每一层都新建一个相同的对象或数组,如果遇到还是对象或数组就再次调用函数进行遍历。

但是该方法有一些缺点,会遇到一些环引用的情况(即对象中包含自己或循环引用),就会导致函数会陷入死循环,从而导致浏览器卡死。

2、使用JSON解析实现深拷贝

在JavaScript中,我们还可以通过JSON对象的解析方法进行深拷贝,如下所示:

var obj1 = {a: 1, b: {c: 2}};
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.b.c = 5;
console.log(obj1.b.c); // 2

通过JSON.parse(JSON.stringify())可以实现一个简单的深拷贝,但是该方法也有一些缺点:

  • 该方法只适用于JSON格式可转的数据类型,对于一些不能转成JSON格式的数据类型如:function、Date等就不能实现深拷贝。
  • 对于包含循环引用的对象或数据也无法正常解析,会进入死循环。
  • 拷贝对象类型时,对象里的function、undefined等会被忽略。

3、使用第三方库进行深拷贝

除了手动实现深拷贝外,也可以使用一些第三方库来进行深拷贝,如lodash、jQuery等。

//使用lodash的cloneDeep()方法进行深拷贝
var obj1 = {a: 1, b: {c: 2}};
var obj2 = _.cloneDeep(obj1);
obj2.b.c = 5;
console.log(obj1.b.c); // 2

通过第三方库的方法进行深拷贝是最简单,最安全的方式。

三、深拷贝的使用方法

深拷贝在实际开发中也非常常用,在以下几个场景中使用:

  • 在实现对象继承时,我们需要对父类对象进行深拷贝以保留其所有属性和方法。
  • 在操作复杂的嵌套结构数据时,深拷贝能够保证不会影响到原数据。
  • 当需要对某个对象或数组进行拷贝,而这个数据又需要改动时,可以使用深拷贝生成一个全新的数据,从而不影响原数据。
//深拷贝操作示例
var obj1 = {a: 1, b: {c: 2}};
var obj2 = _.cloneDeep(obj1);
obj2.b.c = 5;
console.log(obj1.b.c); // 2
console.log(obj2.b.c); // 5

四、深拷贝的优化

我们在使用深拷贝时需要注意,由于深拷贝的过程比较耗费内存资源,我们需要尽可能地减少深拷贝的次数。

比如,如果我们在Vue或React框架中需要对一个对象的某个值进行修改,我们可以直接替换改变对象的指向,而不是对整个对象进行深拷贝,从而提高程序的运行效率。

//Vue组件中示例
data(){
    return {
        obj: {
            a: 1,
            b: 2,
            c: [3, 4, 5]
        }
    }
},
methods: {
    changeValue(val){
        this.obj.b = val;
    }
}

在示例中,如果我们需要更改obj对象的b值,我们可以使用this.obj.b = val;的方式直接进行修改,不需要进行深拷贝。

五、总结

本文重点讲解了深拷贝的背景和实现方式,并给出了实际应用的场景和优化方法。在实际工作中,我们需要根据业务需求选择合适的深拷贝方式,避免出现不必要的问题。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/247462.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 13:21
下一篇 2024-12-12 13:21

相关推荐

  • Python中init方法的作用及使用方法

    Python中的init方法是一个类的构造函数,在创建对象时被调用。在本篇文章中,我们将从多个方面详细讨论init方法的作用,使用方法以及注意点。 一、定义init方法 在Pyth…

    编程 2025-04-29
  • Harris角点检测算法原理与实现

    本文将从多个方面对Harris角点检测算法进行详细的阐述,包括算法原理、实现步骤、代码实现等。 一、Harris角点检测算法原理 Harris角点检测算法是一种经典的计算机视觉算法…

    编程 2025-04-29
  • Python符号定义和使用方法

    本文将从多个方面介绍Python符号的定义和使用方法,涉及注释、变量、运算符、条件语句和循环等多个方面。 一、注释 1、单行注释 # 这是一条单行注释 2、多行注释 “”” 这是一…

    编程 2025-04-29
  • Python下载到桌面图标使用方法用法介绍

    Python是一种高级编程语言,非常适合初学者,同时也深受老手喜爱。在Python中,如果我们想要将某个程序下载到桌面上,需要注意一些细节。本文将从多个方面对Python下载到桌面…

    编程 2025-04-29
  • 瘦脸算法 Python 原理与实现

    本文将从多个方面详细阐述瘦脸算法 Python 实现的原理和方法,包括该算法的意义、流程、代码实现、优化等内容。 一、算法意义 随着科技的发展,瘦脸算法已经成为了人们修图中不可缺少…

    编程 2025-04-29
  • Python匿名变量的使用方法

    Python中的匿名变量是指使用“_”来代替变量名的特殊变量。这篇文章将从多个方面介绍匿名变量的使用方法。 一、作为占位符 匿名变量通常用作占位符,用于代替一个不需要使用的变量。例…

    编程 2025-04-29
  • 百度地区热力图的介绍和使用方法

    本文将详细介绍百度地区热力图的使用方法和相关知识。 一、什么是百度地区热力图 百度地区热力图是一种用于展示区域内某种数据分布情况的地图呈现方式。它通过一张地图上不同区域的颜色深浅,…

    编程 2025-04-29
  • 神经网络BP算法原理

    本文将从多个方面对神经网络BP算法原理进行详细阐述,并给出完整的代码示例。 一、BP算法简介 BP算法是一种常用的神经网络训练算法,其全称为反向传播算法。BP算法的基本思想是通过正…

    编程 2025-04-29
  • Matlab中addpath的使用方法

    addpath函数是Matlab中的一个非常常用的函数,它可以在Matlab环境中增加一个或者多个文件夹的路径,使得Matlab可以在需要时自动搜索到这些文件夹中的函数。因此,学会…

    编程 2025-04-29
  • Python函数重载的使用方法和注意事项

    Python是一种动态语言,它的函数重载特性有些不同于静态语言,本文将会从使用方法、注意事项等多个方面详细阐述Python函数重载,帮助读者更好地应用Python函数重载。 一、基…

    编程 2025-04-28

发表回复

登录后才能评论