当前位置: 首页 > article >正文

js-17-对数组、对象进行浅拷贝和深拷贝

目录

  • 数组
    • 一、浅拷贝
      • 1. 展开运算符...
      • 2. Array.prototype.slice()
    • 二、深拷贝
      • 1. JSON方法
      • 2. 递归函数
  • 对象
    • 一、浅拷贝
      • 1. Object.assign()
      • 2. 展开运算符...
    • 二、深拷贝
      • 1. JSON方法
      • 2. 递归函数

自己总结的一些方法,可能有不到位的地方,欢迎指出

数组

一、浅拷贝

1. 展开运算符…

let arr1 = [1,2,'3',true, { name: '李华'}]
let arr2 = [...arr1] // arr2=[1,2,'3',true, { name: '李华'}]

arr2[0] = 0 // 修改浅拷贝数组中的基本类型元素,原始数组不受影响
arr2[3] = false // 修改浅拷贝数组中的基本类型元素,原始数组不受影响
arr2[4].name = '小帅' // 修改浅拷贝数组中的对象的属性,由于对象是引用类型,所以原始数组中的对象也会受到影响

console.log(arr1) // [1,2,'3',true, { name: '小帅'}]
console.log(arr2) // [0,2,'3',false,{ name: '小帅'}]

2. Array.prototype.slice()

let arr1 = [1, 2, '3', true, { name: '李华'}]
let arr2 = arr1.slice() // arr2=[1,2,'3',true,{ name: '李华'}]

arr2[0] = 0
arr2[3] = false
arr2[4].name = '小帅'

console.log(arr1) // [1, 2, '3', true, { name: '小帅' }]
console.log(arr2) // [0, 2, '3', false, { name: '小帅' }]

二、深拷贝

1. JSON方法

注意:此方法不能处理函数、undefined、Symbol和循环引用

    let arr1 = [1, 2, '3', true, { name: '李华'}]
    let arr2 = JSON.parse(JSON.stringify(arr1))
    
    arr2[0] = 0
    arr2[3] = false
    arr2[4].name = '小帅'
    
    console.log(arr1) // [1, 2, '3', true, { name: '李华'}]
    console.log(arr2) // [0, 2, '3', false, { name: '小帅'}]

2. 递归函数

    function deepClone(obj, hash = new WeakMap()) {
      if (obj === null) return null
      if (obj instanceof Date) return new Date(obj) // 如果是日期对象,则直接返回一个新的日期对象
      if (obj instanceof RegExp) return new RegExp(obj) // 如果是正则对象,则直接返回一个新的正则对象
      // 如果循环引用了就用 weakMap 来解决  
      if (hash.has(obj)) return hash.get(obj);

      let allDesc = Object.getOwnPropertyDescriptors(obj);
      let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);
      hash.set(obj, cloneObj);

      for (let key of Reflect.ownKeys(obj)) {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
          cloneObj[key] = deepClone(obj[key], hash); // 递归复制  
        } else {
          cloneObj[key] = obj[key];
        }
      }
      return cloneObj;
    }

    let arr1 = [1, 2, '3', true, { name: '李华' }, undefined]
    let arr2 = deepClone(arr1)
    arr2[4].name = '小帅'
    
    console.log(arr1) // [1, 2, '3', true, { name: '李华' }, undefined]
    console.log(arr2) // [1, 2, '3', true, { name: '小帅' }, undefined]

对象

一、浅拷贝

1. Object.assign()

    let obj1 = {
      a: 1, 
      b: {
        c: 2
      }
    }
    let obj2 = Object.assign({}, obj1) // obj2={a:1, b: {c:2}}
    
    obj2.a = 100
    obj2.b.c = 200
    
    console.log(obj1) // { a: 1, b: { c: 200 } }
    console.log(obj2) // { a: 100, b: { c: 200 } }

2. 展开运算符…

    let obj1 = {
      a: 1, 
      b: {
        c: 2
      }
    }
    let obj2 = {...obj1}
    
    obj2.a = 100
    obj2.b.c = 200
    
    console.log(obj1) // { a: 1, b: { c: 200 } }
    console.log(obj2) // { a: 100, b: { c: 200 } }

二、深拷贝

1. JSON方法

    let obj1 = {
      a: 1,
      b: {
        c: 2
      },
      d: [3, 4],
      e: undefined, // 注意此方法undefined不会被复制
      f: function(){ console.log('Hello world')} // 注意此方法函数不会被复制
    }
    let obj2 = JSON.parse(JSON.stringify(obj1))
    
    // console.log(obj2) // {a:1, b: {c:2}, d: [3,4]}
    
    obj2.b.c = 200
    obj2.d[0] = 300
    
    console.log(obj1) // { a: 1, b: { c: 2 }, d: [3, 4], e: undefined, f: f()}
    console.log(obj2) // { a: 1, b: { c: 200 }, d: [300, 4] }

2. 递归函数

    function deepClone(obj, hash = new WeakMap()) {
      // 处理基本数据类型和null  
      if (obj === null || typeof obj !== 'object') {
        return obj;
      }

      // 处理日期和正则对象  
      if (obj instanceof Date) {
        return new Date(obj);
      }
      if (obj instanceof RegExp) {
        return new RegExp(obj);
      }

      // 如果已经处理过这个对象,则直接返回缓存的结果  
      if (hash.has(obj)) {
        return hash.get(obj);
      }

      // 根据obj的类型创建一个新的对象或数组  
      let cloneObj = Array.isArray(obj) ? [] : {};
      hash.set(obj, cloneObj); // 将原始对象和克隆对象存储在hash中,以处理循环引用  

      // 递归复制对象的每个属性  
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          cloneObj[key] = deepClone(obj[key], hash);
        }
      }

      // 如果obj是Map或Set,则需要特殊处理  
      if (obj instanceof Map) {
        cloneObj = new Map();
        obj.forEach((value, key) => {
          cloneObj.set(deepClone(key, hash), deepClone(value, hash));
        });
      } else if (obj instanceof Set) {
        cloneObj = new Set();
        obj.forEach(value => {
          cloneObj.add(deepClone(value, hash));
        });
      }

      return cloneObj;
    }

    let obj1 = {
      a: 1,
      b: {
        c: 2
      },
      d: [3, 4],
      e: undefined, // 注意此方法undefined不会被复制
      f: function () { console.log('Hello world') } // 注意此方法函数不会被复制,而且其实通常不深拷贝函数
    }
    let obj2 = deepClone(obj1)
    // console.log(obj2) // { a: 1, b: { c: 2 }, d:[3, 4], e:undefined, f:f()}
    obj2.b.c = 200
    obj2.d[0] = 300
    console.log(obj1) // { a: 1, b: { c: 2 }, d: [3, 4], e: undefined, f: f()}
    console.log(obj2) // { a: 1, b: { c: 200 }, d: [300, 4], e: undefined, f: f() }

http://www.kler.cn/a/320651.html

相关文章:

  • vs2022搭建opencv开发环境
  • RDIFramework.NET CS敏捷开发框架 V6.1发布(.NET6+、Framework双引擎、全网唯一)
  • 2020年计挑赛往届真题(C++)
  • Qt 每日面试题 -10
  • 2024山西省网络建设运维第十八届职业院校技能大赛解析答案(3. ansible 服务)
  • 储能技术中锂离子电池的优势和劣势
  • 四款负载均衡工具Nginx、HAProxy、MetalLB、gobetween 比较
  • 【ARM 嵌入式 编译系列 2.8 -- GCC 编译优化参数 位置无关码】
  • Chat2VIS: Generating Data Visualizations via Natural Language
  • 【Android】BottomSheet基本用法总结(BottomSheetDialog,BottomSheetDialogFragment)
  • Unity中的GUIStyle错误:SerializedObject of SerializedProperty has been Disposed.
  • 隧道面稳定性分析MATLAB
  • 立志最细,在FreeRtos中数据传输方式及应用!!!
  • PostgreSQL 创建表,常规表、外部表、分区表区别讲解
  • 华为HarmonyOS灵活高效的消息推送服务(Push Kit) - 1 简介
  • 前端开发必备:实用Tool封装工具类方法大全
  • vscode【实用插件】Markdown Preview Enhanced 预览 .md 文件
  • 时尚与科技的融合,戴上更轻更悦耳的QCY C30耳夹耳机,随时享受好音乐
  • 计算机毕业设计 基于Python的荣誉证书管理系统 Django+Vue 前后端分离 附源码 讲解 文档
  • python自定义日志等级
  • 企业级-pdf预览-前后端
  • 免费开源的AI 智能网盘,图片和媒体管理工具 | 极空间部署『PicHome』
  • GUI编程18:文本框、密码框、文本域
  • MT76X8、MT7621和MT7981 接NOR FALSH分区表
  • Focalboard开源项目管理系统本地Windows部署与远程访问协同办公
  • C语言读取一行字符_只需要看第四条