首页 > 其他分享 >【个人前端笔记】手写对象深拷贝

【个人前端笔记】手写对象深拷贝

时间:2024-03-04 14:00:42浏览次数:22  
标签:return 笔记 source JSON 引用 dist 手写 拷贝

一、对象深拷贝简单的方法:JSON序列化

  1. 方法
    通过将对象转换成JSON格式并转换回对象,实现深拷贝
let a1 = {
  a:"hello",
  b:"world",
  c:[1,2,3],
  d:{
    a:1,
    b:2
  }
}

let a2 = JSON.parse(JSON.stringify(a1))

console.log(a2);
  1. JSON序列化拷贝的缺点
    a.不支持函数function
    b.不支持undefined
    c.不支持symbol
    d.不支持Date(序列化之后会转换成ISO8601字符串)
    (以上缺点究其原因其实就是因为JSON不支持这些格式)
    5.不支持环状引用 (环状引用就是a.self = a,类似自己引用自己或者引用成环形的结构)
    二、实现手写深拷贝函数
class DeepCloner{
  constructor(){
    this.cache = []
  }

  clone(source){
    //2.对于引用类型(引用类型要么是对象,要么是对象的子类型)我们需要进行判断类型,然后对结果进行响应不同的初始化
    if (source instanceof Object) {
      //3.只要是引用类型,在正式拷贝前我们需要判断这个数据是否曾经出现过
      //如果出现过,说明这是个环引用,那么我们直接返回
      //如果没出现,我们则继续
      let cacheDist = this.cacheFind(source)
      if (cacheDist) {
        return cacheDist
      }else{
        //4.进入到这里说明这个引用类型的数据曾经没有拷贝过
        //我们需要进行一个个的子类型判断,然后进行不同的初始化
        //是数组我们就初始化为数组,是对象我们就初始化为对象
        let dist
        if (source instanceof Array) {
          dist = []
        }else if (source instanceof Function) {
          //5.对于函数类型,我们初始化为一个函数,这个函数调用这个传入进来的函数
          dist = function() {
            return source.call(this,...arguments)
          }
        }else if (source instanceof RegExp) {
          dist = new RegExp(source.source,source.flags)
        }else if (source instanceof Date) {
          dist = new Date(source)
        } else{
          dist = {}
        }
        //6.初始化完毕后,在正式深拷贝前,我们需要进行一个缓存,同时把原数据和新数据进行存储
        //方便我们后续进行判断
        this.cache.push([source,dist])

        //7.开始时进行深拷贝
        for (const key in source) {
          //8.通常我们是会深拷贝数据的原型,因为原型是一个很大的坑,
          //比如原型上有一个函数,那么这个函数的原型又是继承自某个原型
          //将所有原型拷贝将会是一个非常大的工作量,所以不拷贝原型
          //这里判断该类型是否为自身的属性,如果是,则拷贝,不是则跳过
          if (source.hasOwnProperty(key)) {
            dist[key] = this.clone(source[key])            
          }
        }

        //9.拷贝完成后,返回
        return dist
      }
    }
    //1.深拷贝思路,对于普通类型,我们直接返回即可
    return source
  }

  cacheFind(source){
    for (let index = 0; index < this.cache.length; index++) {
      if (this.cache[index][0] === source) {
        return this.cache[index][1]
      }
    }
    return undefined
  }
}

module.exports = DeepCloner

标签:return,笔记,source,JSON,引用,dist,手写,拷贝
From: https://www.cnblogs.com/icerain-black/p/18051675

相关文章

  • Java学习笔记——第五天
    方法什么是方法方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用。定义方法时可以指定形参,形参没有实际意义,仅仅起到占位和提示实参种类的作用,名字要有意义。调用方法时可以指定实参,实参由实际意义,是方法运行时事实上使用的数值。return关键字可以用来......
  • 3.4 STL 学习笔记一
    这是初次学习STL的相关知识。可能之后还会补充笔记。STL是提高C++编写效率的一个利器1.#includevector是变长数组,支持随机访问,不支持在任意位置O(1)插入。为了保证效率,元素的增删一般应该在末尾进行。1.1声明include//头文件vectora;//相当于一个长度变化的int数组......
  • vue3笔记3watch监视的几种变化
    <template> <divclass="about">  <p>情况一,监事ref的值</p>  <h1>求和{{sum}}</h1>  <button@click="changeSum">++++</button> </div></template><scriptlang="ts"......
  • Living-Dream 系列笔记 第28期
    本期讲解了进制转换。T1考验代码能力的好题。首先需要判断输入的坐标是RXCY型还是Excel型:直接扫一遍字符串,若存在一个字母前面是数字,则说明是RXCY型,否则是Excel型。这一部分的代码:boolcheck(strings){ for(inti=0;s[i];i++) if(isupper(s[i])&&isdigit(s[i......
  • Living-Dream 系列笔记 第26期
    ProblemT1见题解。T2/*思路:枚举每一头牛说的话,尝试将Bessie置于pi处,再枚举其他牛说的话,检验不合法的数量,取max即为答案。*/#include<bits/stdc++.h>usingnamespacestd;intn,ans=1e9;structnode{charop;intp;}a[1031];intmain(){cin>>n;......
  • Living-Dream 系列笔记 第25期
    ProblemT1/*思路:对于操作1,直接+=拼接即可;对于操作2,直接令s=s.substr(a,b)即可;对于操作3,直接令s=s.insert(a,t)即可;对于操作4,直接s.find(str)即可,注意特判-1。*/#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intq;strings;signedmain(){......
  • Living-Dream 系列笔记 第23期
    ProblemT1/*思路:我们可以忽略两人碰到后转向的过程,直接视为两人彼此穿过了对方,这样算距离是不变的,时间也是不变的,所以合法。通过上述分析,那么最小时间即为对于每一个士兵往左/右走的时间取min再取max,最大时间反之亦然。*/#include<bits/stdc++.h>usingnamespacestd;......
  • Living-Dream 系列笔记 第24期
    ProblemT1/*思路:暴力枚举所有的和,用桶标记每个和出现的次数,找最大值且编号最小即可。*/#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;ints1,s2,s3;intsum=-1e9,ans;intmp[131];signedmain(){ ios::sync_with_stdio(0); cin>>s1>>s2>>s3;......
  • Living-Dream 系列笔记 第21期
    ProblemT1/*思路:枚举二元组(i,j),依次检验k次训练课,若i的位置总是>j或<j,则将答案累加。*/#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intk,n,ans;inta[31][31];signedmain(){ ios::sync_with_stdio(0); cin>>k>>n; for(inti=1;i<=......
  • Living-Dream 系列笔记 第22期
    ProblemT1/*思路:因为题目要求最大水量,所以K次操作需要都用上,并且由于每次都是将x倒入x+1中,所以K次操作之后的最大水量应当是x~x+k+1之和;于是问题就转变成了求一段长度为k+1的连续子段的和的最大值,因此维护一个前缀和即可。*/#include<bits/stdc++.h>usingnamespacestd......