首页前端开发JavaScriptJavaScript深拷贝的一些踩坑记录

JavaScript深拷贝的一些踩坑记录

时间2024-02-01 04:14:03发布访客分类JavaScript浏览787
导读:收集整理的这篇文章主要介绍了JavaScript深拷贝的一些踩坑记录,觉得挺不错的,现在分享给大家,也给大家做个参考。 前言之前去一家公司面试的时候,面试官问了我一个问题,说:"如何才能...
收集整理的这篇文章主要介绍了JavaScript深拷贝的一些踩坑记录,觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

之前去一家公司面试的时候,面试官问了我一个问题,说:"如何才能深拷贝一个对象"。当时我心里有些窃喜,这么简单的问题还用想吗?于是脱口而出:"平时常用的有两种办法,第一种用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(){ } 这种形式的则会出错

拷贝函数增加函数类型

拷贝结果

@H_401_126@

出错类型

后记

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

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

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

您可能感兴趣的文章:
  • 浅谈JavaScript浅拷贝和深拷贝
  • js中的赋值 浅拷贝和深拷贝详细
  • 详解JS变量存储深拷贝和浅拷贝
  • JS对象复制(深拷贝和浅拷贝)
  • 详解JS深拷贝与浅拷贝
  • 带你搞懂js的深拷贝

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

上一篇: jQuery实现动态粒子效果下一篇:Vue组件传值过程中丢失数据的分析...猜你在找的JavaScript相关文章 html font标签如何设置字体大小?html font标签属性用法介绍2022-05-16vue3+TypeScript+vue-router的使用方法2022-04-16vue3获取当前路由地址2022-04-16如何利用React实现图片识别App2022-04-16JavaScript展开运算符和剩余运算符的区别详解2022-04-16微信小程序中使用vant框架的具体步骤2022-04-16Vue elementUI表单嵌套表格并对每行进行校验详解2022-04-16如何利用Typescript封装本地存储2022-04-16微信小程序中wxs文件的一些妙用分享2022-04-16JavaScript的Set数据结构详解2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

若转载请注明出处: JavaScript深拷贝的一些踩坑记录
本文地址: https://pptw.com/jishu/594906.html
h文件和c文件的关系是什么 C语言中的指针有什么作用

游客 回复需填写必要信息