资讯专栏INFORMATION COLUMN

javascript对深拷贝对象的研坑

caozhijian / 232人阅读

摘要:对于深拷贝,浅拷贝的概念不多说,概念可以自行百度哟这里对深拷贝对象进行一些研究只有值类型数据的深拷贝针对只有值的数据对象,下面一行代码足以不严谨的简单的深拷贝注意这里问题存在没有对参数做检验判断是否对象的逻辑不够严谨没有考虑数组的兼容进阶深

对于深拷贝,浅拷贝的概念不多说,概念可以自行百度哟!这里对深拷贝对象进行一些研究!

只有值类型数据的深拷贝

针对只有值的数据对象,下面一行代码足以!

JSON.parse(JSON.stringify(obj))
不严谨的简单的深拷贝
function clone(source) {
    var target = {};
    for(var i in source) {
        if (source.hasOwnProperty(i)) {
            if (typeof source[i] === "object") {
                target[i] = clone(source[i]); // 注意这里
            } else {
                target[i] = source[i];
            }
        }
    }

    return target;
}

问题存在:

没有对参数做检验

判断是否对象的逻辑不够严谨

没有考虑数组的兼容

进阶深拷贝
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;
}

问题存在:

拷贝环,也就是对 对象循环引用 的拷贝出现问题

针对环的深拷贝

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

function isObj(obj)
{
    return (typeof obj === "object" || typeof obj === "function") && obj !== null
}
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
}

问题存在:

没有考虑对new Date(),正则,函数类型的对象的拷贝

结合环,针对date,reg,箭头函数类型的深拷贝
const obj = {    arr: [111, 222],    obj: {key: "对象"},    a: () => {console.log("函数")},    date: new Date(),    reg: /正则/ig}

function isObj(obj)
{
    return (typeof obj === "object" || typeof obj === "function") && obj !== null
}
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;
        case Function:
            cloneObj = eval(obj.toString());
            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;
}

const cloneObj = deepCopy(obj);
console.log(cloneObj);

更多遗留问题,针对函数进行拷贝,若是function,非箭头函数,如何解决?还有,若要拷贝原型链上的属性?如何拷贝不可枚举属性? 如何拷贝Error对象等等的坑?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100063.html

相关文章

  • 对深拷贝和浅拷贝的全面理解

    摘要:关于深拷贝和浅拷贝从原理看浅拷贝拷贝一层,对象级别的则拷贝引用深拷贝拷贝多层,每个层级的属性都会拷贝从现象看复制了,被修改后,随变化而变化浅拷贝不变深拷贝深拷贝针对的复杂的类型数据如直接赋值的单层拷贝,如,虽然不受的影响,但是这也不算做 关于深拷贝和浅拷贝 从原理看: 浅拷贝:拷贝一层,对象级别的则拷贝引用 深拷贝:拷贝多层,每个层级的属性都会拷贝 从现象看:A复制了B,B被修改后...

    _DangJin 评论0 收藏0
  • JS的深浅拷贝

    摘要:引用类型之所以会出现深浅拷贝的问题,实质上是由于对基本类型和引用类型的处理不同。另外方法可以视为数组对象的浅拷贝。上面描述过的复杂问题依然存在,可以说是最简陋但是日常工作够用的深拷贝方式。 一直想梳理下工作中经常会用到的深拷贝的内容,然而遍览了许多的文章,却发现对深拷贝并没有一个通用的完美实现方式。因为对深拷贝的定义不同,实现时的edge case过多,在深拷贝的时候会出现循环引用等问...

    xiaoxiaozi 评论0 收藏0
  • javascript的深拷贝VS浅拷贝

    摘要:深拷贝浅拷贝本文主要对深拷贝浅拷贝的解释及实现做一下简单记录。之所以会有深拷贝与浅拷贝之分,是因为不同数据类型的数据在内存中的存储区域不一样。但注意,只能做一层属性的浅拷贝。 深拷贝VS浅拷贝 本文主要对深拷贝&浅拷贝的解释及实现做一下简单记录。原文链接,欢迎star。 之所以会有深拷贝与浅拷贝之分,是因为不同数据类型的数据在内存中的存储区域不一样。 堆和栈是计算机中划分出来用来存储的...

    Nekron 评论0 收藏0
  • 一篇文章理解JS数据类型、深拷贝和浅拷贝

    摘要:接下来我们进入正片数据类型六种基本数据类型布尔值,和一个表明值的特殊关键字。一种数据类型,它的实例是唯一且不可改变的。在中是没有方法是可以改变布尔值和数字的。参考资料深拷贝浅拷贝 前言 笔者最近整理了一些前端技术文章,如果有兴趣可以参考这里:muwoo blogs。接下来我们进入正片: js 数据类型 六种 基本数据类型: Boolean. 布尔值,true 和 false. nu...

    EddieChan 评论0 收藏0

发表评论

0条评论

caozhijian

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<