资讯专栏INFORMATION COLUMN

复习Javascript专题(四):js中的深浅拷贝

MobService / 385人阅读

摘要:基本数据类型的复制很简单,就是赋值操作,所以深浅拷贝也是针对,这类引用类型数据。它会抛弃对象的。另外,查资料过程中还看到这么一个词结构化克隆算法还有这一篇资料也有参考,也写得比较详细了的深浅拷贝

基本数据类型的复制很简单,就是赋值操作,所以深浅拷贝也是针对Object,Array这类引用类型数据。

浅拷贝对于字符串来说,是值的复制,而对于对象来说则是对对象地址的复制;

而深拷贝的话,它不仅将对象的各个属性逐个复制出来,还将各个属性所包含的对象也依次复制出来,相当于在堆区又新开了一块地存放,主要采取递归来实现。

实现方式 原生JS实现:

浅拷贝:

let originObj={ color:["red","green"], num:5 };

function shallowClone(obj){
    let newObj=(obj instanceof Array) ? []:{};
    for(let item in obj){
        if(obj.hasOwnProperty(item)){ // 避免列举出原型上的属性
            newObj[item]=obj[item];
        }
    }
    return newObj;
}
let cloneObj=shallowClone(originObj);

深拷贝:

   function deepClone(obj){
       let newObj=(obj instanceof Array)? [] : {};
       for(let item in obj){
           if(obj.hasOwnProperty){
               const val=obj[item];
               debugger
               newObj[item]=typeof val==="object" ? deepClone(val) : val;
           }
       }
       return newObj;
   }
   let cloneObj2=deepClone(originObj);

其实,这种深拷贝的实现还是有些问题的,比如日期正则对象无法复制,还有一个是循环引用,类似闭包会内存泄露一样,这样的对象深拷贝也会陷入一个闭环,直到栈溢出。
为了解决这个问题,就得先判断这个对象是否等于原对象。

function deepClone(obj){
    let tempArr=[];
    let newObj=(obj instanceof Array) ? [] : {};
    tempArr.push(obj);
    for(let item in obj){
        if(typeof obj[item] === "object"){
            const index=tempArr.indexOf(obj[item]); 
            // 如果已存在,证明引用了相同对象,那么无论是循环引用还是重复引用,我们返回引用就可以了
            if(index>-1){
                newObj[item]=tempArr[index];
            }else{
                newObj[item]=obj[item];
            }
        }else{
            newObj[item]=obj[item];
        }        
    }
    return newObj;
}
ES6实现
    let newObj1=Object.assgin({},originObj);
    let newObj2={...obj}; // 数组用[...obj]
注:Object.assgin和扩展运算符实现的都是浅拷贝。
JSON实现:

这种方法简单是简单,不过这个方法有以下缺陷:

1.会忽略函数对象以及原型对象,正则会复制成空对象,而日期对象会变成字符串。

2.它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object; 
   
3.如果对象中存在循环引用的情况无法正确处理。

按需取用吧。

  let originObj={fn:function(){console.log(111)}, colors:["red","gree"],reg:/s/g};
  let newObj=JSON.parse(JSON.stringify(originObj));
第三方库实现:

转自链接:深入剖析 JavaScript 的深复制

Underscore —— _.clone()
顺便安利下underscore,真的挺好用的一个库: Underscore中文文档

这个方法实际上是一种浅复制 (shallow-copy),所有嵌套的对象和数组都是直接复制引用而并没有进行深复制。

        let originObj={ color:["red","green"], num:5 };
        let newObj=_.clone(originObj);
        newObj.colors.push("grey");
        originObj.colors; // ["red","green","grey"]; 

源码逻辑很简单:(当然调用的其他方法也是underscore的)

    // Create a (shallow-cloned) duplicate of an object.
    _.clone = function(obj) {
        if (!_.isObject(obj)) return obj;
        return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
    }
jQuery —— $.extend()

这个用法很简单:

    let originObj={ color:["red","green"], num:5 };
    let shallowClone=$.extend({},originObj); // 浅拷贝
    let deepClone=$.extend(true,{},originObj); // 深拷贝,第一个参数表示是否深度合并对象
lodash —— _.clone() / _.cloneDeep()
lodash深拷贝——这个算是这几个里面最完善的方法了,日期函数正则对象通通都能复制。

在lodash中关于复制的方法有两个,分别是_.clone()_.cloneDeep()。其中_.clone(obj, true)等价于_.cloneDeep(obj)

没引入的可以点击上面的文档链接去直接改动代码试试看。

另外,查资料过程中还看到这么一个词:结构化克隆算法
还有这一篇资料也有参考,也写得比较详细了:JS的深浅拷贝

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

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

相关文章

  • javascript深浅拷贝

    摘要:为何写最近在研究深浅拷贝,找了很多资料,感觉不是很满意,所以自己就整理了一份。深拷贝如果给放到新的内存中,将的各个属性都复制到新内存里,就是深拷贝。安全的值是指能够呈现为有效格式的值。参考文档冴羽的专题之深浅拷贝深拷贝与浅拷贝的实现 为何写: 最近在研究深浅拷贝,找了很多资料,感觉不是很满意,所以自己就整理了一份。废话不多说,我们来一起复习一下吧,也希望留下您宝贵意见。 何为深浅拷贝?...

    LMou 评论0 收藏0
  • 复习Javascript专题(一):基本概念部分

    摘要:一数据类型基本类型引用类型类型判断返回结果未定义布尔值字符串数值对象或者函数拓展堆栈两种数据结构堆队列优先,先进先出由操作系统自动分配释放,存放函数的参数值,局部变量的值等。 一、数据类型 基本类型:`Null Boolean String Undefined Number(NB SUN)` 引用类型:`Array Function Object` 类型判断:typeof 返回结果...

    LiangJ 评论0 收藏0
  • JS专题深浅拷贝

    摘要:在之前的文章专题之数据类型和类型检测中我有讲过,中的数据类型分为两种,基本数据类型和引用数据类型,基本数据类型是保存在栈的数据结构中的是按值访问,所以不存在深浅拷贝问题。 前言 在开发过程中,偶尔会遇到这种场景,拿到一个数据后,你打算对它进行处理,但是你又希望拷贝一份副本出来,方便数据对比和以后恢复数据。 那么这就涉及到了 JS 中对数据的深浅拷贝问题,所谓深浅拷贝,浅拷贝的意思就是,...

    ASCH 评论0 收藏0
  • JavaScript专题深浅拷贝

    摘要:专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路前言拷贝也是面试经典呐数组的浅拷贝如果是数组,我们可以利用数组的一些方法比如返回一个新数组的特性来实现拷贝。所以我们可以看出使用和是一种浅拷贝。 JavaScript 专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路 前言 拷贝也是面试经典呐! 数组的浅拷贝 如果是数组,我们可以利用数组的一些方法比如:slice、co...

    RancherLabs 评论0 收藏0
  • JavaScript专题系列文章

    摘要:专题系列共计篇,主要研究日常开发中一些功能点的实现,比如防抖节流去重类型判断拷贝最值扁平柯里递归乱序排序等,特点是研究专题之函数组合专题系列第十六篇,讲解函数组合,并且使用柯里化和函数组合实现模式需求我们需要写一个函数,输入,返回。 JavaScript 专题之从零实现 jQuery 的 extend JavaScritp 专题系列第七篇,讲解如何从零实现一个 jQuery 的 ext...

    Maxiye 评论0 收藏0

发表评论

0条评论

MobService

|高级讲师

TA的文章

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