资讯专栏INFORMATION COLUMN

JS 中的深拷贝与浅拷贝

ztyzz / 701人阅读

摘要:什么是深拷贝浅拷贝见名知义,无论是深拷贝还是浅拷贝,都是的问题。使用如下以上就是关于中的深拷贝与浅拷贝的知识和如何进行深拷贝的知识了,如果有错或者有其他方式的话,欢迎在下面留言评论啦

前言 最近在写项目的时候涉及到一些父子组件传递个对象或者数组通信啥的,或者是直接复制添加对象啥的,直接使用赋值的时候总会出错。一查原来是浅拷贝的问题,就从网上找了点资料,汇总到这里来了。

1 什么是深拷贝&浅拷贝

见名知义,无论是深拷贝还是浅拷贝,都是 copy 的问题。就是 copy 的时候出现的两种情况。区分起来也挺简单的,举个例子,假设 B 是 A 复制过来的,当我们修改 A 的时候,B 也随之改变了,那么这个就是浅拷贝,那要是 B 没有随 A 一起改变的话,那么这个就深拷贝了。

2 现实场景

首先呢,我们先要明白在 Javascript 中,有 5 种简单数据类型(也称为基本数据类型),分别是 Undefined,Null,String,Number,Boolean,还有 1 种复杂数据类型即 Object,(ES6 新出的 Symbol 数据类型就先不讨论了)

2.1 基本数据类型

对于基本数据类型的复制就谈不上什么深拷贝和浅拷贝了,对于基本数据类型来说,他们的值在栈内存中占据着固定大小的空间,并被保存在栈内存中。假设 变量 b 复制 基本数据类型变量 a,那么 b 会内存中占据自己的空间,和 a 就没啥关系了,大家各管各的,互不干涉。

let a = 2; 
let b = a;
b = 4;
console.log(a); // 2
console.log(b); // 4
2.2 复杂数据类型(Object)

对于对象的话,他是引用类型,复制起来就要区分浅拷贝和深拷贝了,因为 Object 是引用类型,他真正的值保存在堆内存中,他在栈内存存储是变量名和指向该对象值的指针(就是一个地址),如下图所示。

所以当我们用平常用一个变量去复制一个 Object 类型的变量的时候,复制的是他的指针地址而已,所以两个变量最终都指向同一个变量,大家要改一起改,这就是浅拷贝啦,如下

let obj1 = {name:"kk",age:12,desc:"源对象"}
let obj2 = obj1;
obj2.desc = "目标对象"
console.log(obj1); //{name:"kk",age:12,desc:"目标对象"} 此处源对象跟着一起变了
console.log(obj2); // {name:"kk",age:12,desc:"目标对象"}

啥,不信?!,那就看图

如何

但是在我们日常的使用当中,Object 类型的浅拷贝的行为会让我们很迷,我复制这个对象就是想复制他的值而已啦,不要复制人家个值就和他绑到一块了,跟他一起「同生共死」。所以啊,当我们想按照我们复制的想法,就只复制他的值用来自己用,他的是他的,我的是我的,大家井水不犯河水。接下来就要说咋办了。

3 实现对象类型的深拷贝

对于对象的深拷贝,搜集了网上的资料,就有下面三种方法

3.1 slice()&concat()

这个是针对数组的深拷贝,可以通过这两个方法实现对数组的深拷贝,如下

let arr = [1,2,3,4]
let arr2 = arr.slice();
arr[0] = 0;
console.log(arr); //[1,2,3,4]
console.log(arr2); //[1,2,3,4]

concat 同理可得,不过这两个方法有个问题,slice()concat() 方法能够深拷贝的就只有数组的一级属性,但是如果是多维数组的话,那么只有一级属性的值是深拷贝,往下就都是浅拷贝了,如下所示

let arr = [[1,2],2,3,4]
let arr2 = arr.concat();
arr[0][0] = 0;
arr[1] = 1;

console.log(arr); //[[0,2],1,3,4]

console.log(arr2); //[[0,2],2,3,4]
// arr2[1] 没变,但是 arr2[0] 跟着一起改了

3.2 JSON 的骚操作

通过 JSON 的 stringify, parase 操作也可以实现对象的深拷贝。

let obj1 = {name:"kk",age:12,desc:"源对象"}
let obj2 = JSON.parase(JSON.stringify(obj1));
obj2.desc = "目标对象";
console.log(obj1); //{name:"kk",age:12,desc:"源对象"} 此处源对象就没有一起变了
console.log(obj2); // {name:"kk",age:12,desc:"目标对象"}

此法数组和对象都可以用。

3.3 自己写一个深拷贝函数

自己动手,丰衣足食

function deepCopy(obj) {
  let newObj = Array.isArray(obj) ? [] : {};
  if (obj && typeof obj === "object") {
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        //判断ojb子元素是否为对象,如果是,递归复制
        if (obj[key] && typeof obj[key] === "object") {
          newObj[key] = deepCopy(obj[key]);
        } else {
          //如果不是,简单复制
          newObj[key] = obj[key];
        }
      }
    }
  }
  return newObj;
}

let a = [1,2,3];
let b = deepCopy(a);
a[0] = 0;
console.log(a); //[0,2,3]
console.log(a); // [1,2,3]
3.4 JQ 的 extend 方法

这个就直接放文档了
$.extend( [deep ], target, object1 [, objectN ] )
deep:如果设为true,则递归合并即深拷贝。
target:待修改对象。
object1:待合并到第一个对象的对象。
objectN:待合并到第一个对象的对象。
使用如下

let a = [1,2,3],
let b = $.extend(true,[],a);
a[0]=1;
console.log(a); // [0,2,3]
console.log(b); // [1,2,3]

以上就是关于 JS 中的深拷贝与浅拷贝的知识和如何进行深拷贝的知识了,如果有错或者有其他方式的话,欢迎在下面留言评论啦

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99393.html

相关文章

  • JS的深拷贝与浅拷贝

    摘要:中的深拷贝与浅拷贝说到深浅拷贝的时候就不得不说一下中的变量类型了基本类型按值存放在栈内存中的简单数据段可以直接访问引用类型存放在堆内存中的对象变量保存的是一个指向存放数据位置的指针访问引用类型的值时首先从栈中获取到存放该数据位置的指针然后再 JS中的深拷贝与浅拷贝 说到深浅拷贝的时候就不得不说一下JS中的变量类型了: 基本类型: undefined、null、boolean、numb...

    ARGUS 评论0 收藏0
  • JS的深拷贝与浅拷贝

    摘要:深拷贝和浅拷贝最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用,深拷贝在计算机中开辟了一块内存地址用于存放复制的对象,而浅拷贝仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅拷贝出来的对象也会相应改变。 深拷贝和浅拷贝最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用, 深拷贝在计算机中开辟了一块内存地址用于存放复制的对象, 而浅拷贝仅仅是指向被...

    wuyumin 评论0 收藏0
  • 低门槛彻底理解JavaScript的深拷贝和浅拷贝

    摘要:案例中的赋值就是典型的浅拷贝,并且深拷贝与浅拷贝的概念只存在于引用类型。修改修改经测试,也只能实现一维对象的深拷贝。经过验证,我们发现提供的自有方法并不能彻底解决的深拷贝问题。 在说深拷贝与浅拷贝前,我们先看两个简单的案例: //案例1 var num1 = 1, num2 = num1; console.log(num1) //1 console.log(num2) //1 num...

    wind3110991 评论0 收藏0
  • 浅谈深拷贝和浅拷贝

    摘要:而引用类型值是指那些保存堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。而堆内存主要负责对象这种变量类型的存储。我们需要明确一点,深拷贝与浅拷贝的概念只存在于引用类型。 深拷贝和浅拷贝 说起深拷贝和浅拷贝,首先我们来看两个栗子 // 栗子1 var a = 1,b=a; console.log(a); console.log(b) ...

    littleGrow 评论0 收藏0
  • javascript的深拷贝VS浅拷贝

    摘要:深拷贝浅拷贝本文主要对深拷贝浅拷贝的解释及实现做一下简单记录。之所以会有深拷贝与浅拷贝之分,是因为不同数据类型的数据在内存中的存储区域不一样。但注意,只能做一层属性的浅拷贝。 深拷贝VS浅拷贝 本文主要对深拷贝&浅拷贝的解释及实现做一下简单记录。原文链接,欢迎star。 之所以会有深拷贝与浅拷贝之分,是因为不同数据类型的数据在内存中的存储区域不一样。 堆和栈是计算机中划分出来用来存储的...

    Nekron 评论0 收藏0

发表评论

0条评论

ztyzz

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<