手写JS—深拷贝

news2024/11/17 3:38:38

什么是深拷贝

一个引用对象一般来说由两个部分组成:一个具名的Handle,也就是我们所说的声明(如变量)和一个内部(不具名)的对象,也就是具名Handle的内部对象。它在Manged Heap(托管堆)中分配,一般由新增引用对象的New方法是进行创建。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。

方法一:JSON序列化实现深拷贝

  • JSON.stringfy():可以将JavaScript类型转成对应的JSON字符串;
  • JSON.parse():可以解析JSON,将其转回对应的JavaScript类型

   JSON序列化实现深拷贝的优缺点:

  • 如果只是对一个简单对象进行深拷贝,那么使用该方法是很方便的;
  • 但根据上面的打印结果可以发现,原obj的方法属性并没有被拷贝到newObj中;
  • JSON序列化只能对普通对象进行深拷贝,如果对象中包含函数、undefined、Symbol等类型的值是无能为力的,会直接将其忽略掉;

方法二:自定义函数

一般简单来说我们都会这么写但是 会有循环引用的问题

什么是循环引用:

  • 循环引用指两个对象相互强引用了对方,即retain了对方,从而导致两个对象都无法被释放,引发了内存泄漏现象。
  • 在开发中很容易出现循环引用,循环引用可能存在于代码的每个角落,会使内存消耗过高,性能变差,也可能会导致程序崩溃。
  • 其实就是   A.point = B;   B.point = A;
function copy(obj){
        let newobj = null;
        if(typeof(obj) == 'object' && obj !== null){ 
            newobj = obj instanceof Array? [] : {};   
            for(var i in obj){  
                newobj[i] = copy(obj[i])
            }
        }else{
            newobj = obj
        }    
      return newobj;
   }
let objF = {
  a:1,
}
objF.a = objF
const deepObj=copy(objF);

用 WeakMap() 或者Map()记录下对象中的所有对象,并与新创建的对象一一对应,即记录引用关系

代码:

let s1 = Symbol("aaa")
let s2 = Symbol("bbb")
const obj = {
  name: 'byj',
  age: 18,
  friend: {
    name: 'abc',
  },
  hobbies: ["abc", "cba", "nba"],
  // 函数类型
  foo: function( ) {
    console.log("foo function")
  },
  // Symbol作为key和value
  [s1]: "abc",
  s2: s2,
  // Set/Map
  set: new Set(['aaa', 'bbb', 'ccc']),
  map: new Map([
    ['aaa', 'abc'],
    ['bbb', 'cba'],
  ]),
  ud:undefined
};

/**
 * 深拷贝
 * @param {any} obj 要拷贝的数据
 * @param {Map| WeekMap} wMap 弱类型引用 放置循环引用
 * @returns 
 */
function deepClone(obj ,wMap = new WeakMap()){
  //function
  if(typeof obj==="function"){
    return obj
  }
  //undefined
  if(typeof obj==="undefined"){
    return undefined
  }
  // Map
  if(obj instanceof Map){
    return new Map([...obj])
  }
  //Set
  if(obj instanceof Set){
    return new Set([...obj])
  }
  //Symobl
  if(typeof obj==="symbol"){
    return Symbol(obj.description);
  }
  //值类型  
  if(typeof obj!="object"&&typeof obj!="function"&&obj!=null){
    return obj
  }
  if(wMap.has(obj)){
    console.log(wMap)
    return wMap.get(obj)
  }
  
  const newData=Array.isArray(obj)?[]:{}
  wMap.set(obj,newData)
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      newData[key] = deepClone(obj[key],wMap);
    }
  }

  const symbolKeys=Object.getOwnPropertySymbols(obj);
  for (const iterator of symbolKeys) {
    newData[iterator]=deepClone(obj[iterator],wMap)
  }
  return newData;
  
}
function copy(obj){
  let newobj = null;
  if(typeof(obj) == 'object' && obj !== null){ 
      newobj = obj instanceof Array? [] : {};   
      for(var i in obj){  
          newobj[i] = copy(obj[i])
      }
  }else{
      newobj = obj
  }    
return newobj;
}


function isObject(value) {
  const valueType = typeof value
  return (value !== null) && (valueType === "object" || valueType === "function")
}
let objF = {
  a:1,
}
objF.a = objF
const deepObj=deepClone(obj);
console.log(deepObj)

const deepObj2=deepClone(objF);
console.log(deepObj2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/73136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Real diff算法是怎么运作的?

React 的 Reconciliation 算法原理 React 的渲染机制 Reconciliation 过程 React 采用的是虚拟 DOM (即 VDOM ),每次属性 (props) 和状态 (state) 发生变化的时候,render 函数返回不同的元素树,React 会检测当前返回的元素树和上次渲染的元素…

论文阅读笔记 | 三维目标检测——PV-RCNN算法

如有错误,恳请指出。 文章目录1. 背景2. 网络结构2.1 Feature Encoder and Proposal Generation2.2 voxel-to-keypoint scene encoding2.3 Keypoint-to-grid RoI Feature Abstraction3. 实验部分paper:《PV-RCNN: Point-Voxel Feature Set Abstraction f…

JavaScript -- DOM事件总结

文章目录事件1 事件对象简介2 Event对象3 冒泡4 事件的委派5 事件的捕获事件 1 事件对象简介 事件对象是由浏览器在事件触发时所创建的对象,这个对象中封装了事件相关的各种信息通过事件对象可以获取到事件的详细信息比如:鼠标的坐标、键盘的按键…浏览…

单频信号的相位谱计算与误差修正-附Matlab代码

一、问题描述 我们在实际处理时经常遇到只有一个正弦信号的情况,其频率为 f0{{f}_{0}}f0​,在谱分析以后,除了在频率为 f0{{f}_{0}}f0​处有相位数值外,其他频率处都有相位数值,分析其他频谱出现相位值的原因。 例如…

外部tomcat资源整合

Spring Boot应用默认是以jar包方式运行的,Springboot默认有内置的tomcat,在启动的时候会自动的将项目发布,这样各有利弊。 优点:简单,便携 缺点:不支持jsp, 定制优化比较麻烦,需要自己编写ser…

如何开发一个婚恋交友系统?开发功能特点有什么?

婚恋平台为年轻人开启了一个交流恋爱的方式,一方面为的是适龄的年轻单身人士,另一方面为一部分大龄单身人士,解决单很多身人 士的需求,婚恋平台的开发,跟随着互联网的发展,抢占了小程序的热门市场&#xf…

Java线程实现

内容引用自《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)周志明》 线程的实现 我们知道,线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和 执行调度分开,各个…

React框架入门

React是用于构建用户界面的JavaScript库, 起源于Facebook的内部项目,该公司对市场上所有 JavaScript MVC框架都不满意,决定自行开发一套,用于架设Instagram的网站。于2013年5月开源 一、React简介 React以声明式编写 UI&a…

0119 动态规划 Day8

剑指 Offer 10- I. 斐波那契数列 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下: F(0) 0, F(1) 1 F(N) F(N - 1) F(N - 2), 其中 N > 1…

计算机的硬件系统和软件系统的关系

计算机的硬件系统和软件系统的关系是缺一不可。 硬件它是所有软件运行的物质基础。 与硬件直接接触的是操作系统,它处在硬件和其他软件之间,表示它向下控制硬件,向上支持其他软件。 在操作系统之外的各层分别是各种语言处理程序、数据库管理…

CleanMyMacX4.12.1Crack版本频繁弹密码 菜单浮窗无法显示显示空白解决办法

你们有没有出现过在使用 CleanMyMac 清理系统垃圾文件的时候会频繁弹出输入开机密码?那么该如何解决这个问题呢?跟着小编来看看解决方法吧! 频繁输入密码 更新CleanMyMacX到4.12.1的Crack版本之后,发现做一些操作要一直输入密码&…

科技云报道:PingCAP黄东旭:Serverless是数据库的未来形态

科技云报道原创。 30年前,程序员要想写代码,必须使用复杂的汇编语言。 但在今天,几乎没有程序员知道如何使用汇编语言,更加简易的高级语言如C,C#,JAVA,Rust,Go已成为开发主流。 随…

分布式文件存储系统FastDFS[3]-通过Docker安装并且从客户端进行上传下载测试

一、FastDFS安装 FastDFS的安装我们还是通过Docker来安装实现吧,直接在Linux上还装还是比较繁琐的,但就学习而言Docker安装还是非常高效的。Docker环境请自行安装哦,不清楚的可以看看我的Docker专题的内容。https://blog.csdn.net/qq_3852657…

【jenkins】1. 安装jenkins (docker-compose)

环境 ubuntu 20docker服务器 ip:xxx.xxx.xxx.xxx 步骤 1. 【编写安装文件】windows下 - 编写 docker-compose.yaml version: "3.1" services:jenkins:image: jenkins/jenkinsrestart: alwayscontainer_name: jenkinsports:- 58080:8080- 50000:50000volumes:- ./…

5.31 综合案例2.0 - 在线MP3音乐播放器

综合案例2.0 - 在线MP3音乐播放器一、案例说明二、准备器件三、案例连线四、代码代码说明复制五、测试一、案例说明 本案例制作一个联网下载声音文件的MP3播放器。 案例功能说明: 案例使用一块IC035串口屏和两个按键通过按键可以切换音乐,下载播放或删除…

瑜岿科技综合能源管理系统助力企业节能降耗工作

能源是国民经济的基础,更是城市赖以发展的动力。优化能源结构、大力发展可再生能源、提高机房能效、实现建筑智慧节能是行业绿色发展重点。在国家碳达峰碳中和的重大战略决策背景下,我国能源体制改革深入推进,能源生产和消费发生重大变革&…

如今社交电商不可忽略的一个点——消费增值

消费增值是一个基于消费返利理论的全新商业消费生态,一个让用户从优惠消费—免单消费—挣钱消费,所突破的新消费、新业态模式—增值消费,一个从电商化的平台走向品牌化的平台,让平台脱离单打独斗的方式,通过商家联盟方…

编译原理 2 - 词法分析

第3章 词法分析3.1 词法分析器的功能和结构3.2 状态转换图3.3 正则文法 和 正则表达式3.4 有限自动机 DFA与NFA测试第3章 词法分析 重点:① 词法分析器的输入、输出;② 用于识别符号的状态转移图的构造;③ 根据状态转移图实现词法分析器 难点…

【MATLAB教程案例55】GoogleNet网络的MATLAB编程学习和实现,以步态识别为例进行仿真分析

欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程》 目录 1.软件版本 2.GoogleNet理论概述

基于Qt的桌面客户端组件化框架DT 开源啦

这个是本人在工作中基于QT开发的组件化桌面开发框架,目前打算开源出来提供给大家,节省大家的开发时间和效率,希望对大家的开发有所帮助,也欢迎提出意见和改进建议 1. 为什么开源DT框架 DT框架,本身就是基于QT为基础搭…