iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >JavaScript深拷贝的一些踩坑记录
  • 811
分享到

JavaScript深拷贝的一些踩坑记录

2024-04-02 19:04:59 811人浏览 安东尼
摘要

前言 之前去一家公司面试的时候,面试官问了我一个问题,说:"如何才能深拷贝一个对象"。当时我心里有些窃喜,这么简单的问题还用想吗?于是脱口而出:"平时常用的有两种办法,第一种用JSO

前言

之前去一家公司面试的时候,面试官问了我一个问题,说:"如何才能深拷贝一个对象"。当时我心里有些窃喜,这么简单的问题还用想吗?于是脱口而出:"平时常用的有两种办法,第一种用JSON.parse(jsON.stringify(obj)),第二种可以使用for...in加递归完成"。面试官听了以后点了点头觉得挺满意的。
当时我也并没有太过在乎这个问题,直到前段时间又想起这个问题,发现上面说的两种方法都是有Bug的。

提出问题

那么上面所说的Bug是什么呢?

特殊对象拷贝

首先让我们试想有这么一个对象,在不考虑普通类型的情况下,它有如下成员:


const obj = {
    arr: [111, 222],
    obj: {key: '对象'},
    a: () => {console.log('函数')},
    date: new Date(),
    reg: /正则/ig
}

然后我们用上面两种方式分别拷贝一次

JSON法


JSON.parse(JSON.stringify(obj))

输出结果:

可以从中看出,obj中的普通对象和数组都能拷贝,然而date对象成了字符串,函数直接就不见了,正则成了一个空对象。
再来看看for...in加递归的方法

递归


function isObj(obj) {
    return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj) {
    let tempObj = Array.isArray(obj) ? [] : {}
    for(let key in obj) {
        tempObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key]
    }
    return tempObj
}

结果:

结论

通过上面的测试可知,这两个方法都无法拷贝函数,date,reg类型的对象;

什么是环?

环就是对象循环引用,导致自己成为一个闭环,例如下面这个对象:


var a = {}

a.a = a

使用上面两个方法拷贝一下会直接报错

解决方案

可以使用一个WeakMap结构存储已经被拷贝的对象,每一次进行拷贝的时候就先向WeakMap查询该对象是否已经被拷贝,如果已经被拷贝则取出该对象并返回,将deepCopy函数改造成如下


function deepCopy(obj, hash = new WeakMap()) {
    if(hash.has(obj)) return hash.get(obj)
    let cloneObj = Array.isArray(obj) ? [] : {}
    hash.set(obj, cloneObj)
    for (let key in obj) {
        cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key];
    }
    return cloneObj
}

拷贝环结果:

特殊对象的拷贝

这个问题的解决比较麻烦,因为需要特别对待的对象种类实在太多,于是我参考了MDN上的结构化拷贝,然后结合解决环的方案:


// 只解决date,reg类型,其他的可以自己添加

function deepCopy(obj, hash = new WeakMap()) {
    let cloneObj
    let Constructor = obj.constructor
    switch(Constructor){
        case RegExp:
            cloneObj = new Constructor(obj)
            break
        case Date:
            cloneObj = new Constructor(obj.getTime())
            break
        default:
            if(hash.has(obj)) return hash.get(obj)
            cloneObj = new Constructor()
            hash.set(obj, cloneObj)
    }
    for (let key in obj) {
        cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key];
    }
    return cloneObj
}

拷贝结果:

完整版可以查看lodash深拷贝

  • 函数的拷贝

但是MDN上的结构化拷贝依旧没有解决函数的拷贝

目前为止,我只想到使用eval的方法对函数进行拷贝,但是这种方法只能对箭头函数生效,如果是fun(){}这种形式的则会出错

拷贝函数增加函数类型

拷贝结果

出错类型

后记

javascript的深拷贝还不止上面所说的这些坑,还存在的问题有如何拷贝原型链上的属性?如何拷贝不可枚举属性? 如何拷贝Error对象等等的坑,在这里就不一一赘述了。

不过在日常过程中还是建议使用JSON方法,这个方法已经覆盖了绝大部分的业务需求,所以不需要把简单的事情复杂化,不过面试中如果遇到面试官钻牛角尖对这个问题的解答绝对可以秀他一脸了。

到此这篇关于JavaScript深拷贝的一些踩坑记录的文章就介绍到这了,更多相关JavaScript深拷贝内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: JavaScript深拷贝的一些踩坑记录

本文链接: https://www.lsjlt.com/news/121861.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript深拷贝的一些踩坑记录
    前言 之前去一家公司面试的时候,面试官问了我一个问题,说:"如何才能深拷贝一个对象"。当时我心里有些窃喜,这么简单的问题还用想吗?于是脱口而出:"平时常用的有两种办法,第一种用JSO...
    99+
    2024-04-02
  • javascript深拷贝和浅拷贝的区别有哪些
    这篇文章主要介绍“javascript深拷贝和浅拷贝的区别有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“javascript深拷贝和浅拷贝的区别有哪些”文章能...
    99+
    2024-04-02
  • javascript深拷贝的情况有哪些
    这篇“javascript深拷贝的情况有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“javascript深拷贝的情况有...
    99+
    2023-06-26
  • javascript赋值、浅拷贝、深拷贝的概念
    本篇内容介绍了“javascript赋值、浅拷贝、深拷贝的概念”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2024-04-02
  • javaScript深拷贝和浅拷贝的简单介绍
    目录基本数据类型在数据结构当中引用数据类型浅拷贝-深拷贝浅拷贝浅拷贝小结深拷贝结尾源码地址在了解深拷贝和浅拷贝之前,我们先梳理一下: JavaScript中,分为基本数据类型(原始值...
    99+
    2024-04-02
  • vue2.xbackground:url()的踩坑记录
    目录background:url()的踩坑记录backgroundImage路径问题处理方法background:url()的踩坑记录 开发模式下vue中background: ur...
    99+
    2024-04-02
  • Golang的strings.Split()踩坑记录
    目录背景场景前置排查验证打印底层信息追源码类似情况总结背景 工作中,当我们需要对字符串按照某个字符串切分成字符串数组数时,常用到strings.Split() 最近在使用过程中踩到了...
    99+
    2024-04-02
  • 一文带你了解JavaScript基础之深拷贝和浅拷贝
    目录浅拷贝深拷贝补充总结拷贝(又名克隆,复制等),但是又分深拷贝和钱拷贝。 其实这个问题有时候想通了就很简单,如果想不通可能会有点绕,不过其难度比闭包等好理解的多。 为什么又这个概念...
    99+
    2024-04-02
  • JavaScript中的深拷贝(deep copy)和浅拷贝(shallow copy)
    聚沙成塔·每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造...
    99+
    2023-10-19
    javascript 开发语言 ecmascript
  • javascript怎么深拷贝一个对象
    这篇文章将为大家详细讲解有关javascript怎么深拷贝一个对象,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。JavaScript的作用是什么1、能够嵌入动态文本于HTML页面。2、对浏览器事件做出响应...
    99+
    2023-06-14
  • 如何理解JavaScript中的浅拷贝与深拷贝
    本篇文章给大家分享的是有关如何理解JavaScript中的浅拷贝与深拷贝,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 浅拷贝在使用JavaScript对数组进行操作...
    99+
    2023-06-16
  • javascript中深拷贝函数有哪些
    这篇文章将为大家详细讲解有关javascript中深拷贝函数有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。JavaScript可以做什么1.可以使网页具有交互性,例如响应用户点击,给用户提供更好的体...
    99+
    2023-06-14
  • JavaScript深浅拷贝的介绍
    本篇内容介绍了“JavaScript深浅拷贝的介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!了解拷贝背后的过程,避免不必要的错误,Js专...
    99+
    2023-06-07
  • 关于TypeScript的踩坑记录
    目录用字符串做下标报错函数内使用this报错找不到模块XXX引入模块提示找不到声明文件(接上一个问题)JSON直接解析localStorage值报错初始加载的组件未命名,浏览器打开页...
    99+
    2024-04-02
  • JavaScript中的深拷贝和浅拷贝的详细介绍
    这篇文章主要介绍“JavaScript中的深拷贝和浅拷贝的详细介绍”,在日常操作中,相信很多人在JavaScript中的深拷贝和浅拷贝的详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,...
    99+
    2024-04-02
  • JavaScript中浅拷贝和深拷贝的区别是什么
    本篇文章为大家展示了JavaScript中浅拷贝和深拷贝的区别是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前言1. 基础数据类型: undefined、bo...
    99+
    2024-04-02
  • JavaScript深拷贝的注意事项
    小编给大家分享一下JavaScript深拷贝的注意事项,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!之前去一家公司面试的时候,面试官问了我一个问题,说:"如何才能深拷贝一个对象"。当时我心里有些窃喜,这...
    99+
    2023-06-14
  • JSON.stringify实现深拷贝的坑怎么解决
    这篇“JSON.stringify实现深拷贝的坑怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JSON.string...
    99+
    2023-07-02
  • javascript深拷贝实现的方式有哪些
    本篇内容主要讲解“javascript深拷贝实现的方式有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“javascript深拷贝实现的方式有哪些”吧!概念介绍深拷贝:在堆内存中重新开辟一个存...
    99+
    2023-07-02
  • Spring Boot统一返回体的踩坑记录
    前言 在Spring Boot项目中我们可以通过RestControllerAdvice配合实现ResponseBodyAdvice<T>接口来保证Spring MVC接...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作