前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >javascript对深拷贝对象的研坑

javascript对深拷贝对象的研坑

作者头像
张炳
发布2019-08-02 16:17:27
4490
发布2019-08-02 16:17:27
举报
文章被收录于专栏:web全栈工程师的取经之路

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

只有值类型数据的深拷贝

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

代码语言:javascript
复制
JSON.parse(JSON.stringify(obj))

不严谨的简单的深拷贝

代码语言:javascript
复制
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;
}

问题存在:

  • 没有对参数做检验
  • 判断是否对象的逻辑不够严谨
  • 没有考虑数组的兼容

进阶深拷贝

代码语言:javascript
复制
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函数改造成如下:

代码语言:javascript
复制
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,箭头函数类型的深拷贝

代码语言:javascript
复制
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对象等等的坑?

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 只有值类型数据的深拷贝
  • 不严谨的简单的深拷贝
  • 进阶深拷贝
  • 针对环的深拷贝
  • 结合环,针对date,reg,箭头函数类型的深拷贝
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档