浅谈对象(数组)的深克隆和浅克隆

news/2024/7/19 12:50:24 标签: js

浅谈对象(数组)的深克隆和浅克隆

浅克隆

  • object.assign()
  • Array.prototype.concat()
  • Array.prototype.slice()

深克隆

  • JSON.stringify 和 JSON.parse
  • Object.assign()
  • 通过JQuery中的extend方法实现深拷贝
  • lodash.cloneDeep()实现深拷贝
  • 递归

注意:当对象只有一层结构的时候,使用Object.assign()是深拷贝,但是对象里面要是有子对象,就是浅拷贝

浅克隆

浅拷贝值复制某个对象的指针,而不是复制对象本身,新旧对象还是使用共同的内存,深拷贝为对象创建另一个一样的对象,修改新对象不会更改旧对象。

所以当浅拷贝的对象中含有二级对象的时候,二级对象的值其实是一个引用地址,该引用地址指向堆内存,当我们拷贝到时候,也是直接考的这个引用地址,所以修改堆中的数据的时候对原始对象和拷贝后的对象都有影响。

以下面这个obj为例,画个图相信大家就懂了。
在这里插入图片描述

1、object.assign()
使用Object.assign()是浅拷贝,当对象只有一层的时候是深拷贝,但是有子结构就是浅拷贝

  let obj = {
     name:'bella',
     addr:{
        province:'cd',
        city:'df'
     },
     age:13
  }
  let clone = Object.assign({},obj);
  clone.addr.city = 'aaa';
  console.log(obj.addr.city);// aaa

2、Array.prototype.concat()

  let arr = [1, 3, {
      username: 'kobe'
      }];
  let arr2=arr.concat();    
  arr2[2].username = 'wade';
  console.log(arr[2].username);// wade

3、Array.prototype.slice()

  let arr = [1,3,{
     username:'bella'
  }];
  let arr2 = arr.slice();
  arr2[2].username = 'dada';
  console.log(arr[2].username);//dada

深克隆

1、JSON.stringify 和 JSON.parse

用JSON.stringify把对象转换成字符串,再用JSON.parse把字符串转换成新的对象

可以转成JSON格式的对象才能使用这种方法,如果对象中包含function或者RegExp、Date这些就不能使用这个方法

  function deepClone(obj){
     let _obj = JSON.stringify(obj);
     let objClone = JSON.parse(_obj);
     return objClone
  }

2、Object.assign()拷贝

当对象中只有一级属性的时候,就是深拷贝,要是有二级属性,在二级属性以后,就是浅拷贝。

3、通过JQuery中的extend方法实现深拷贝

  let $ = require("./jquery");
  let obj1 ={
     a:1,
     b:{
        f:{
           g:1
        }
     },
     c:[1,2,3]
  }
  
  let obj2 = $.extend(true,{},obj1);

4、lodash.cloneDeep()实现深拷贝

  let _ = require('lodash');
  let obj1 = {
      a: 1,
      b: { f: { g: 1 } },
      c: [1, 2, 3]
  };
  let obj2 = _.cloneDeep(obj1);

5、递归

原理:遍历对象、数组知道里边都是基本数据类型,然后再去复制,就是深度拷贝

这里传过来的obj,要是 是fn(比如)的实例,并且obj.constructor就是fn,所以这里的newObj就是在创建fn的另一个实例(高逼格)

function deepClone(obj) {
    // 不直接创建空对象目的:克隆的结果和之前保持相同的所属类 
    var newObj = new obj.constructor;
    if(obj === null) return null;
    if(typeof obj !=='object') return obj;
    if(obj instanceof RegExp) return new RegExp();
    if(obj instanceof Date) return new Date();

    for(let key in obj){
        if(obj.hasOwnProperty(key)){
            newObj[key] = deepClone(obj[key])
        }
    }
    return newObj;
}

http://www.niftyadmin.cn/n/1029967.html

相关文章

EAUML日拱一卒-状态图::重画按钮状态图

按钮处理模块的状态图,在前面的文章中已经说明过了,但是当我们对信号系统引擎建模时,发现当初的设计并不能满足需求,所以需要对已经完成的模型进行修改。 这样的修改在软件开发过程中经常出现,需要做的不是抑制这种修改…

EAUML日拱一卒-状态图::状态机之间的同步

今天是交通信号系统连载的最后一篇,首先还是回顾一下系统的构成。还是请出对象图。 这个系统的基本设计如下: 每个设备都拥有自己的状态机,在独立的线程中执行,这些状态机相互独立,互不干扰。 交通信号系统引擎Traffi…

一道关于EventLoop事件循环事件队列的JS题

一道关于EventLoop事件循环事件队列的JS题 上代码 async function async1(){console.log("async1 start");await async2();console.log(async1 end);}async function async2(){console.log(async2)};console.log(script start);setTimeout(function(){console.log(…

对管理者说[转载CSDN]

在这里,我还有一些话要对IT公司的管理人员们说。只当是为程序员们说说心理话吧。请不要在招聘的时候过于夸大公司,虚假承诺。程序员们能够忍让,但是有一定的限度。试用期中我们可以发现很多的真实情况。在招聘到公司认为合适的人才之后&#…

EAUML日拱一卒-多任务编程超入门-(1) 什么是多任务

多任务可以说是编程中的一个难点,对于非计算机专业的开发者来讲,尤其如此。本系列希望可以用尽量浅显的语言对多任务编程进行说明,在满足多任务编程基本要求的同时,提供继续深入研究提供一个良好的出发点。 我们的文章首先一一个…

js引入的defer和async区别

js引入的defer和async区别 defer 解析HTML遇到带有defer属性的script标签,继续解析HTML,同时下载script引入的文件浏览器解析完HTML后,再执行下载的脚本文件 async 解析html遇到带有async属性的script标签,继续解析HTML文件&…

家乡的大师--儒雅文士吴敬梓

在我国清代中叶,有一位著名的讽刺小说家,他曾经多次参加清代的科考,终因名落孙山,看透世态炎凉,积十年之功夫写成了我国著名的讽刺小说《儒林外史》。 他就是可与著名的法国作家巴尔扎克、西班牙的塞万提斯&#xff0c…

EAUML日拱一卒-多任务编程超入门-(2)进程和线程

作为多任务编程的基本概念,进程和线程的概念是无论如何回避不了的。很多公司面试时也会问倒二者的区别。如果到互联网上随便搜一下,就能找到关于进程和线程的文章,但是相信读过之后,懂得人会点头,不懂的还是不懂。所以…