深入了解js中的深拷贝与浅拷贝

本文详细阐述了JavaScript中深拷贝与浅拷贝的概念及其区别,并提供了多种实现方法,帮助开发者更好地理解并运用到实际工作中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据处理在前端的工作中是非常重要的一部分,深入了解js的深拷贝与浅拷贝可以帮助我们在处理后端接口数据时更加得心应手,也非常明确每一个处理可能带来的影响。

一、js中的数据类型

在了解深拷贝与浅拷贝之前,我们先来了解一下js的数据类型,
在js中,数据类型可以分为如下两类:

  1. 基本数据类型(Number、boolean、String、NULL、undefined、Symbol(ES6))
  2. 引用数据类型
    在这里插入图片描述

如上图所示,

1. 基本数据类型的数据名字和值都会保存在栈内存中
2. 引用数据类型,名字保存在栈内存中,值保存在堆内存中,而且栈内存中保存了指针,用于指向堆内存中的值。

由上我觉得可以简单把基本数据类型和引用数据类型理解为栈内存变量和堆内存变量,而所谓的深拷贝和浅拷贝,其实都是围绕堆栈内存来展开的,就是处理值与处理指针的问题。

二、直接赋值、浅拷贝与深拷贝的区别

之前一直以为赋值就是浅拷贝的一种,但其实不然,我们先来了解一下他们的含义。

  1. 赋值:将一个通过=号的方式直接赋值给另一个变量时,赋的是该对象在栈中的指向堆内存中值的指针,而不是在堆中的数据。
  2. 浅拷贝:浅拷贝会先创建一个新对象,再去遍历原对象,如果原对象的属性值是基本类型,那么拷贝的就是基本类型的值,如果属性值是引用类型,那么拷贝的就是指针。
  3. 深拷贝:深拷贝会拷贝所有的属性,以及它们的指针。

上图举例加深理解:

var a = [1, [1,2,3]]
var b=a;//直接赋值
var b= a.concat(); //浅拷贝
var b=JSON.parse(JSON.stringify(a)) //深拷贝
b[0]=2;
b[1].push(4)
console.table(a);
console.table(b);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

粗略的原理图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、浅拷贝深拷贝的实现方式

一百度我们就会发现有几个同样的方法,有的人认为它是浅拷贝,而有的人则认为它是深拷贝。根据前两步以及它们的原理我们可以得知,同样的方法,面对不同的对象,它是可以既是深拷贝也是浅拷贝的。

1.既可是浅拷贝又可是深拷贝的方法:

1.1 Object.assign()
属性全为基本类型时为深拷贝

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

属性中有引用类型时为浅拷贝

var obj = {
    a: 1,
    b:{c:1}
}
var obj1 = Object.assign({},obj);
obj1.b.c = 3;
console.log(obj.b.c) // 3

1.2 Array.prototype.concat()

let arr1=arr.concat();    

1.3 Array.prototype.slice()

let arr1 = arr.slice();

1.4 扩展运算符(…)

let arr3 = [...arr1];
// 或 let obj1 = {...obj};

下面的方法跟第一种同理,不再赘述。

2.常用的深拷贝方法

2.1 JSON.parse(JSON.stringify(object))

不管是基本类型还是引用类型的属性发生改变都互不影响。

let a = {
    name: "凌云00",
    book: {
        title: "快点加薪升职吧",
        price: "12000"
    }
}
let b = JSON.parse(JSON.stringify(a));

a.name = "凌云01";
a.book.price = "20000";
console.table(a);
console.table(b);

在这里插入图片描述

此方法的弊端:

  1. 会忽略undefine
  2. 会忽略symbol
  3. 不能序列化函数
  4. 会忽略空字符串
let obj = {
    name: '凌云',
    a: undefined,
    b: Symbol('凌云'),
    c: function() {},
    d:null,
    e:{},
    f:""
}
let b = JSON.parse(JSON.stringify(obj));
console.table(b);

在这里插入图片描述

  1. 不能解决循环引用的对象(会报错)
    在这里插入图片描述

  2. 不能正确处理new Date()
    在这里插入图片描述

  3. 不能处理正则
    在这里插入图片描述

2.2 jQuery.extend()

var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝

2.3 lodash.cloneDeep()

let obj1 = _.cloneDeep(obj)

已经有人手动写得非常完善了,直接上链接
逐步深入手动实现深拷贝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值