美文网首页
js的深拷贝与浅拷贝 代码实现

js的深拷贝与浅拷贝 代码实现

作者: mudssky | 来源:发表于2021-03-17 16:42 被阅读0次

01.关于深拷贝和浅拷贝的定义

js总共有7种数据类型 ,其中Number,String,Boolean,Null,Undefined,Symbol是值类型,Array,Object是引用类型
Symbol是es6中新加入的语法,用于表示独一无二的值。

引用类型在赋值变量的时候,赋值只会拷贝引用的地址,这种做法有好处也有坏处,好处就是赋值操作的效率只需要赋值一个地址,效率很高。缺点是,当我修改赋值的变量也会改变原来变量中的数据,因为这两个变量是同一个地址,修改的是同一片数据。

所以引用类型当我们需要拷贝一个新的变量的时候,需要自己实现深拷贝或者浅拷贝

浅拷贝就是拷贝的时候,对于引用类型只进行简单的赋值,也就是只拷贝一份地址,以后修改变量的时候改的是同一份内存区域的内容

深拷贝就是拷贝的时候,对于引用类型对地址指向的内容进行拷贝。

一般情况下,浅拷贝的方法就够用了。因为拷贝的东西越多,其实效率也就越低,深拷贝还是尽量避免比较好。

02.浅拷贝的代码实现

举个例子,实现卡池抽卡gacha的功能的时候,我们把每张卡的信息都用一个对象进行描述,把这些对象都放在一个数组里就形成了卡池gachaPool

每张卡都有一个抽取概率,卡池所有卡的抽卡概率和为1。这样就可以用一个随机数函数实现基本的抽卡模拟了,随机0-1之间的数字,看看结果落在哪个区间上就是哪张卡。抽到的卡我们用一个新数组resultList来存储。

如果直接把卡牌的对象push到resultList里 ,假设我们抽到卡以后需要修改抽到的卡对象上的一个数据,或者加上什么属性,就会影响到卡池里的卡的属性,这显然是不合理的。我们需要拷贝一个新的对象。

如果我们修改的数据不包括引用类型,那么只需要浅拷贝就可以。

下面就是我实现浅拷贝的代码:

shallowClone (sourceObj) {
      const newObj = {}
      for (const key in sourceObj) {
        if (Object.hasOwnProperty.call(sourceObj, key)) {
          newObj[key] = sourceObj[key]
        }
      }
      return newObj
    },

上面使用的遍历对象的方法是一种兼容性比较好的方法

for in 可以遍历对象自身的和继承(也就是原型链上的)的可枚举属性(不含 Symbol 属性),但是我们通常只需要遍历对象自身的属性,所以用hasOwnProperty就可以过滤出自身的属性。

上面的方式碰到数组和对象之类的类型的时候,也是普通的赋值(拷贝地址),所以你抽到的卡里面的对象和卡池列表里的gachaPool卡的数组类型和对象类型的数据是一样的。因为卡片目前没有对象或者数组类型的数据,所以这样的浅拷贝也能满足使用需求了。

03.深拷贝的实现

01.最简单版本

一个比较简单的方法是利用json序列化的api

JSON.parse(JSON.stringify())

这个方法的缺点是,不能拷贝函数,没有处理循环引用等。而且效率也比较低。

02.基础版本

我们需要对于常见的场景中Object和Array类型的数据,进行判断,对于这类数据,用递归的方法,对他们进行深拷贝。

function deepClone (target) {
      if (typeof target === 'object') {
        let cloneTarget = Array.isArray(target) ? [] : {}
        for (const key in target) {
          cloneTarget = deepClone(target[key])
        }
        return cloneTarget
      } else {
        return target
      }
    }

这个版本还存在着一些问题,比如用for in 进行遍历,所以不会遍历到symbol类型数据,也就是不会拷贝symbol类型数据,同时也没有对函数进行处理,还有没有解决循环引用的问题,还有一个问题,因为使用了递归,所以层数过深的时候,可能导致栈溢出。

不过已经在很多场景下满足使用需求了。

相关文章

  • js浅拷贝深拷贝

    js浅拷贝,深拷贝的简单实现 基础数据 浅拷贝 深拷贝

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • js深拷贝浅拷贝

    目录 一.数据类型 二.浅拷贝与深拷贝 三.赋值和浅拷贝的区别 四.浅拷贝的实现方式 五.深拷贝的实现方式 一.数...

  • 黑马C++视频笔记《封装、对象属性》

    浅拷贝与深拷贝说明代码: 输出:

  • js的深拷贝与浅拷贝 代码实现

    01.关于深拷贝和浅拷贝的定义 js总共有7种数据类型 ,其中Number,String,Boolean,Null...

  • 深拷贝、浅拷贝

    父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 深拷贝同浅拷贝的区别:浅拷贝...

  • 面试题整理

    父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 深拷贝同浅拷贝的区别:浅拷贝...

  • 2020前端高频面试题总结(附答案)

    [ js基础题 ] 1. new的实现原理是什么? 2. 深拷贝和浅拷贝的区别是什么 深拷贝 浅拷贝 3. bin...

  • 重新认识js复杂类型数据的引用和深浅拷贝

    js 基本概念———— 数据类型 js 深浅拷贝之概念 代码实现 —— 数组和对象的j浅拷贝 代码实现 —— 数组...

  • 面试 (一) : 基础篇

    父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。• 深拷贝同浅拷贝的区别:浅拷...

网友评论

      本文标题:js的深拷贝与浅拷贝 代码实现

      本文链接:https://www.haomeiwen.com/subject/gbsecltx.html