JavaScript 中的浅拷贝和深拷贝

一.前言每一个前端的 JavaScript 之路不一定是由《JavaScript 高级程序设计》开启的,但是每一位前端都一定被“按值传递”和“按引用传递”这两个概念坑过。现在你我应该都很清楚,在 JavaScript 中的object类型是按引用传递的,但是在函数参数中,所有参数都是按值传递的。我们今天要谈的东西,就起源于object型数据的复制与再操作,简单来说,就是我们今天的主题:对象的浅...
摘要由CSDN通过智能技术生成

一.前言

每一个前端的 JavaScript 之路不一定是由《JavaScript 高级程序设计》开启的,但是每一位前端都一定被“按值传递”和“按引用传递”这两个概念坑过。现在你我应该都很清楚,在 JavaScript 中的object类型是按引用传递的,但是在函数参数中,所有参数都是按值传递的。

我们今天要谈的东西,就起源于object型数据的复制与再操作,简单来说,就是我们今天的主题:对象的浅拷贝和深拷贝。

二.按引用传递是什么含义?

首先,我们需要快速回想一下在 JavaScript 中基本数据类型有哪些,请看下面:

1. number
2. string
3. boolean
4. null
5. undefined
6. symbol

引用数据类型只有一种:

object

当然,由此衍生出来的变种也有很多,包括Array,function等等,也可以看成是对象的一种。

接着我们得复习下 JavaScript 的堆栈中是怎么存储数据的。在 JS 中内存的使用和分配与其他语言也大同小异:

堆是动态分配内存,内存大小不一,也不会自动释放。栈是自动分配相对固定大小的内存空间,并由系统自动释放。

对以上6种基本数据类型来说,

当我们在 JavaScript 中声明一个简单基础数据类型并初始化它的值时:

const NAME = 'waw';

此时这个值将以键值对的形式key:'NAME', value:'waw'保存在栈中。

但是对引用类型的数据来说却并不是如此,对它来说,虽然也是以键值对形式存储于栈中,但是value部分存储的是指向堆中的地址,如:key:'NAME', value: 指向堆的指针,而value真正的值则存储在堆中。而在 JavaScript 中是不允许直接操作堆中的内容的,所以我们日常操作对象时实际上操作的是对象的引用。

到这儿为止,咱们的提前知识储备已经差不多了,从上面的内容我们可以达成一个基础的共识,那就是基础数据类型是没有浅拷贝深拷贝之说的,大家都是存储在栈中的社会主义公民,都很平等。所以为了接下来讲解的层次性,我将从数组和对象,基本数据类型和引用数据类型,两种角度出发来给大家讲讲浅拷贝和深拷贝。

三.JavaScript 的浅拷贝

3.1 从基本数据类型的数组角度来说

形如var arr = [1, '1', true, null, undefined, Symbol()],这一类数组内元素的集合,我们都可以称它们为基本数据类型的数组。

浅拷贝最简单的就是var a = b了。举个例子:

var arr = [1, '1', true, null, undefined, Symbol()];
var arrCopy = arr;
arrCopy[0] = 2;
console.log(arr)   
console.log(arrCopy)

结果如下:
在这里插入图片描述

很明显,这就是个最简单的浅拷贝。当然我们也可以自己实现一个基础的浅拷贝函数:

function shallowClone(obj){
   
    let cloneObj = {
   }; 
    for(let key in obj){
   
        if(obj.hasOwnProperty(key)){
   
            cloneObj[key] = obj[key];
        }
    }
    return cloneObj;
}

3.2 从引用数据类型的数组角度来说

什么是引用数据类型的数组?举个简单例子,形如[[1, 2], {age: 1}, Number(1), String(2)]的数组内元素的集合,都可以称为引用数据类型。当然,我们平常在业务中最常见的就是多维数组或者是对象数组。

对它来说,浅拷贝最直接的方式也是var a = b;举个例子:

var arr = [[1, 2], {
   age: 1}, Number(1), String(2)];
var arrCopy = arr;
arrCopy[0] = [3, 4];
console.log(arr)   
console.log(arrCopy)

结果如下:
在这里插入图片描述

3.3 从对象角度来说

从对象角度来说,它就不像数组那样好区分基本数据类型和引用数据类型了,因为毕竟是key=> value键值对形式来存储的结构。

我们一般也可以通过var a=b来进行浅拷贝。举个例子:

var arr = {
   name:'waw', age:1};
var arrCopy = arr;
arrCopy.name = 'gcc';
console.log(arr)   
console.log(arrCopy)

结果如下:
在这里插入图片描述

这儿有个很有意思的事,ES6有一个Object.assgin()方法,可以拷贝(合并)对象并返回新对象。我们试试用它来复制上面的对象看会输出什么:


                
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值