• web前端面试-- js深拷贝的一些bug,特殊对象属性(RegExp,Date,Error,Symbol,Function)处理,循环引用weekmap处理


    本人是一个web前端开发工程师,主要是vue框架,整理了一些面试题,今后也会一直更新,有好题目的同学欢迎评论区分享 ;-)

    web面试题专栏:点击此处


    深拷贝和浅拷贝的区别

    在JavaScript中,深拷贝和浅拷贝是两种不同的对象复制方式。

    浅拷贝是指将一个对象的引用复制给另一个对象,这意味着两个对象将共享相同的内存地址。当修改其中一个对象时,另一个对象也会受到影响。

    深拷贝是指创建一个新的对象,并将原始对象的所有属性逐个复制到新对象中。这意味着两个对象是完全独立的,修改其中一个对象不会影响另一个对象。

    浅拷贝示例

    let obj1 = { name: "Alice", age: 25 };
    let obj2 = obj1; // 浅拷贝
    
    obj2.name = "Bob";
    
    console.log(obj1.name); // 输出: Bob,因为obj1和obj2共享相同的引用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    深拷贝示例

    let obj1 = { name: "Alice", age: 25 };
    let obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝
    
    obj2.name = "Bob";
    
    console.log(obj1.name); // 输出: Alice,因为obj1和obj2是完全独立的对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在上面的深拷贝示例中,我们使用 JSON.stringify() 将原始对象转换为字符串,然后使用 JSON.parse() 将字符串转换回对象。这样做可以创建一个新的对象,并将原始对象的属性逐个复制到新对象中,从而实现深拷贝。

    需要注意的是,深拷贝有时可能会有性能和内存消耗的问题,尤其是对于包含循环引用或大量嵌套对象的复杂对象。因此,在选择深拷贝或浅拷贝时,需要根据具体情况进行权衡。


    特殊对象属性

    • RegExp:不能拷贝
    • Date:时间对象会转换成字符串
    • Error:错误对象会转换成{}
    • Symbol:不能拷贝
    • Function:不能拷贝

    测试对象如下:

    var obj = {
      name: "penk",
      age: 30,
      boo: true,
      n: null,
      un: undefined,
      sy: Symbol("penk value"),
      // big: 10n, // 浏览器没这个,nodejs可以
      child: {
        name: "penk son",
      },
      arr: [1, 2, 3, 4],
      reg: /^\d+$/,
      fn: function () {
        console.log(this.name);
      },
      time: new Date(),
      err: new Error("蛋疼"),
    };
    JSON.parse(JSON.stringify(obj));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    obj对象

    在这里插入图片描述

    JSON转换对象

    虽说是深拷贝,但是有些属性不行。

    在这里插入图片描述

    obj与JSON转换对象对比

    在这里插入图片描述

    手写深拷贝

    封装好deepCopy

    1. 处理了特殊对象属性的拷贝
    2. 对于循环引用,进行了(WeekMap)去重处理。
    // 深拷贝函数
    // 避免对象中存在重复应用的优化方案
    // 通过set集合的方式,obj不同才会进行操作
    function deepCopy(obj, treated = new WeakMap()) {
      // null 也是一个对象...
      // typeof 不是object,可以直接拷贝~
      // 下方数据类型可以直接返回 
      // Undefined|Number|String|Boolean|Null|Function|Symbol
      // 1. Object跟Array 需要递归处理
      // 2. Regexp Error Date 数据问题需要重新NEW
      if (obj == null || typeof obj !== "object") return obj;
      
      // 对象的类型
      // console.log =>  '[object Object]'  '[object Array]'
      let string = Object.prototype.toString.call(obj);
      
      // 对象的构造函数
      let ctor = obj.constructor;
      // 如果有这个obj这个键名,则直接返回键值
      if (treated.has(obj)) return treated.get(obj);
    
      let newObj = {};
    
      // 是个复合数据类型,放的是地址
      treated.set(obj, newObj);
    
      if (string.includes("Object")) {
        // for of 不能遍历普通对象,只能遍历iterator 对象
        for (let i in obj) {
          newObj[i] = deepCopy(obj[i], treated);
        }
    
        return newObj;
      } else if (string.includes("Array")) {
        // 是数组
        for (let i = 0; i < obj.length; i++) {
          newObj = []
          newObj.push(deepCopy(obj[i], treated));
        }
      } else if (string.includes("RegExp")) {
        // 是正则对象
        newObj = new ctor(obj);
      } else if (string.includes("Date")) {
        // 是日期对象
        newObj = new ctor(obj);
      } else if (string.includes("Error")) {
        // 是Error对象
        newObj = new ctor(obj.message);
      }
    
      return newObj;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    打印如下:

    在这里插入图片描述

    obj与deepCopy转换对象对比

    对象是数组类型兼容性已经修改好了~

    在这里插入图片描述

  • 相关阅读:
    Vue源码:手写patch函数,diff算法
    异步爬小说
    Spring注解驱动之BeanPostProcessor后置处理器详解
    【Leetcode】446. Arithmetic Slices II - Subsequence
    简明误差卡尔曼滤波器(ESKF)及其推导过程
    基础矩阵F的计算(2D-2D)
    可编程计数器/定时器8253
    java字符串专项训练(手机号屏蔽)
    Linux 提权-Capabilities
    C++手敲基于梯度图和像素数量数组的OTSU阈值分割
  • 原文地址:https://blog.csdn.net/cs492934056/article/details/133762316