手写支持函数、日期和正则的深拷贝

简介: 手写支持函数、日期和正则的深拷贝

使用const data = JSON.parse(JSON.stringify(x))完成的深拷贝

可解决大部分情况下深拷贝需求,但不支持Date、正则、undefined、函数等数据,且不支持引用。

所以此时需要一个更完备的深拷贝方法。

先上最终代码

const cache = new Map()
    function deepClone(obj){
      if(typeof obj !== 'object' || obj === null) return obj;
      if(cache.get(obj)){
        return cache.get(obj)
      }
      let result = {}
      if(obj instanceof Function){ // 不能100%拷贝
        if(obj.prototype){
            result = function(){ 
                return obj.apply(this,arguments)
            }
        }else{
           result = (...args) => a.call(undefined, ...args)
        }
      }
      if(obj instanceof Array){ 
        result = []
      }
      if(obj instanceof Date){ 
        result = new Date(obj - 0)
      }
      if(obj instanceof RegExp){ 
        result = new RegExp(obj.source, obj.flags)
      }
      cache.set(obj, result)
      for(let key in obj){
        result[key] = deepClone(obj[key])
      }
      return result
    }
    // 测试数据
    const obj1 = {
      number:1, bool:false, str: 'hi', empty1: undefined, empty2: null,
      array: [
      {name: 'hy', age: 18},
      {name: 'jacky', age: 19}
      ],
      date: new Date(2000,0,1,20,30,0),
      regex: /\.(j|t)sx/i,
      obj: { name:'frank', age: 18},
      f1: (a, b) => a + b,
      f2: function(a, b) { return a + b }
    }
    obj1.self = obj1
    const obj2 = deepClone(obj1)
    obj1.array[0] = 'xxx'

基本实现

// 创建函数
function deepClone(obj){
    // 创建返回值变量
    let result = {}
    return result
}
function deepClone(obj){
    /* 其他代码 */
    //传参不为对象 直接return
    if(typeof obj !== 'object' || obj === null) return obj;
    /* 其他代码 */
}
function deepClone(obj){
    /* 其他代码 */
    // 传参为函数
    if(obj instanceof Function){ // 不能100%拷贝
        //普通函数
        if(obj.prototype){
            result = function(){
                return obj.apply(this,arguments)
            }
        }else{
           //箭头函数
           result = (...args) => a.call(undefined, ...args)
        }
    }
    /* 其他代码 */
}
function deepClone(obj){
    /* 其他代码 */
    // 传参为数组
    if(obj instanceof Array){ 
      result = []
    }
    /* 其他代码 */
}
function deepClone(obj){
    /* 其他代码 */
    // 传参为日期
    if(obj instanceof Date){ 
      // obj为日期时,则格式如 -> Sun Jun 19 2022 20:03:03 GMT+0800 (中国标准时间)
      // obj - 0 则得到此时间戳 -> 1655640152585
      // 再将此时间戳赋予到new Date中
      result = new Date(obj - 0)
    }
    /* 其他代码 */
}
function deepClone(obj){
    /* 其他代码 */
    // 传参为正则
    if(obj instanceof RegExp){ 
        result = new RegExp(obj.source, obj.flags)
    }
    /* 其他代码 */
}
function deepClone(obj){
    /* 其他代码 */
    // 基本赋值
    for(let key in obj){
        // 有些属性是继承,有些属性是自身,我们只遍历自身属性
        if(obj.hasOwnProperty(key)){
            // 直接赋值是不行的,因为obj[key]也有可能是对象,直接赋值就变成了浅拷贝
            // result[key] = obj[key] 
            // 正确写法,赋值前调用深拷贝方法,如果是普通类型则不变,如果为对象类型则进行深拷贝。
            result[key] = deepClone(obj[key])
        }
    }
    /* 其他代码 */
}

基本完成

function deepClone(obj){
      if(typeof obj !== 'object' || obj === null) return obj;
      let result = {}
      if(obj instanceof Function){ // 不能100%拷贝
        if(obj.prototype){
            result = function(){
                return obj.apply(this,arguments)
            }
        }else{
           result = (...args) => a.call(undefined, ...args)
        }
      }
      if(obj instanceof Array){ 
        result = []
      }
      if(obj instanceof Date){ 
        result = new Date(obj - 0)
      }
      if(obj instanceof RegExp){ 
        result = new RegExp(obj.source, obj.flags)
      }
      for(let key in obj){
         if(obj.hasOwnProperty(key)){
            result[key] = deepClone(obj[key])
         }
      }
      return result
    }
    // 测试数据
    const obj1 = {
      number:1, bool:false, str: 'hi', empty1: undefined, empty2: null,
      array: [
      {name: 'frank', age: 18},
      {name: 'jacky', age: 19}
      ],
      date: new Date(2000,0,1,20,30,0),
      regex: /\.(j|t)sx/i,
      obj: { name:'frank', age: 18},
      f1: (a, b) => a + b,
      f2: function(a, b) { return a + b }
      }
    const obj2 = deepClone(obj1)
    obj1.number = 2

解决环状问题

之前已经可以满足普通的深拷贝需要了,但此时还有个问题

那就是在深拷贝前,如果变量obj1的self等于自身,也就是说先做了obj1.self = obj1的操作。

之后我们再运行const obj2 = deepClone(obj1)这行代码,则会报错..

number :1,
 array :
( name :
 name :
 boot : false , str :' hi ',empty1: undefined ,empty2: null ,
 JaCky ”
 date : new Date (2000,0,1,20,30,0), regex :
/.( j | t ) sx /1,{ name :' frank ,,
( a , b )= t a + b 
 function ( a , b ){ return a + b }
 age :18),
 undefined 
obj1.self=obj1
¥{ number : I , bool : false , str :' hi ', emptyl : undefined ,empty2: null ,-
> array :(2)[-),(-)]
 bool : false 
 date : Sat Jan 01200020:30:00 GT +0800(中国标准时间))empty1: undefined 
empty2: null 
> fl :( a , b ) m > a + b >f2: f ( a , b )
 number :1
 obj :{ name :' frank ', age :18)
 rene 
 A .( jlt ) sx / i 
 self :
 array :(2)[(-),{)] bool :fal5e
> date : Sat Jan 01200020:30:00 GT +e808(中国标准时间)()
 emptyl : undefined empty2: null 
>f1:( a , b )-> a + b 
>f2: f ( a , b )
 number :1
> obj :{ name :' frank ', age :18)
 reoex :/.( j | t ) sx / i 
 self :
 str :“ hi "
>[ lPrototypel ]: Object 
: fnumber :1, bool : false , str :' hi ',empty1: undefined ,empty2: null ,-)
const obj1={
 number :1,
 array :
 name :
 name :
 boot : false , str :' hi ',empty1: undefined ,empty2: nutl ,
 frank , age : o 
 jacky ', age :
 date : new Date (2000,0,1,20,30,0),
『巴 gex :
八.( jlt ) sx / i ,
 obj :
 name :' Trank ,
 age :18),
1:
( a , b )-- a + b ,
f2:
 function ( a , b ){ return a + b }
< undefined 
 objl . self =obj1
< fnumber :1, booi : false , str :' hi ', emptyl : undefined ,empty2: null ,-}> const obj2= deepClone (obj1)
> Uncaught RangeError : Maximum call 
 at deepClone (< anonymous >:1:21)
 deepClone 
(< anonymous >:29:23)
 deepClone 
(< anonymous >:29:23)
 deepClone 
(< anonymous >:29:23)
 deepClone 
(< anonymous >:29:23)
 deepClone 
(< anonymous >:29:23)
 deepClone 
(< anonymous >:29:23)
 deepClone 
(< anonymous >:29:23)
 deepClone 
(< anonymous >:29:23)
 deepC lone 
(< anonymous >:29:23)
 stack size exceeded 

如何解决...

// 第一步
const cache = new Map()
function deepClone(obj){
    /* 其他代码 */
    // 第二步
    if(cache.get(obj)){
        return cache.get(obj)
    }
     /* 其他代码 */
    // 第三步
    cache.set(a, result)
    for(let key in obj){
      if(obj.hasOwnProperty(key)){
        result[key] = deepClone(obj[key])
      }
    }
    /* 其他代码 */
}

此时再运行obj1.self = obj1 + const obj2 = deepClone(obj1),就不会再报错啦

const obj1=
 numoer :1
 array :( name :
 name :
 bool : false , str :' hi ', emptyl : undefined ,empty2: nuti ,
 frank , age :
 o :
 JaCKy , age :
 date : new Date (2000,0,1,20,30,0),
 regex ;
.( jlt ) sx / i ,
 ooJ :, f name :' frank ', age :18),
( a , b )=> a + b ,
2
 function ( a , b ){ return a + b }
< undefined 
obj1.self=obj1
-> numDer :1,DO0l:
: false , str :' hi ', emptyl : undefined ,empty2: null ,-}
 const obj2= deepClone (obj1)


目录
相关文章
|
4月前
|
Python
python函数的参数学习
学习Python函数参数涉及五个方面:1) 位置参数按顺序传递,如`func(1, 2, 3)`;2) 关键字参数通过名称传值,如`func(a=1, b=2, c=3)`;3) 默认参数设定默认值,如`func(a, b, c=0)`;4) 可变参数用*和**接收任意数量的位置和关键字参数,如`func(1, 2, 3, a=4, b=5, c=6)`;5) 参数组合结合不同类型的参数,如`func(1, 2, 3, a=4, b=5, c=6)`。
36 1
|
SQL HIVE
【hive】字符串操作,截取想要的字符串
字符串操作,截取想要的字符串
1703 0
【hive】字符串操作,截取想要的字符串
|
4月前
|
关系型数据库 MySQL Linux
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
|
4月前
|
机器学习/深度学习 数据采集 自然语言处理
python函数参数的传递、带星号参数的传递,2024年大厂Python高级面试题分享
python函数参数的传递、带星号参数的传递,2024年大厂Python高级面试题分享
|
4月前
|
Java C# 开发者
Python 中的类型注解是一种用于描述变量、函数参数和返回值预期类型的机制
【5月更文挑战第8天】Python的类型注解提升代码可读性和可维护性,虽非强制,但利于静态类型检查(如Mypy)。包括:变量注解、函数参数和返回值注解,使用内置或`typing`模块的复杂类型,自定义类型注解,以及泛型模拟。类型注解可在变量声明、函数定义和注释中使用,帮助避免类型错误,提高开发效率。
50 6
|
11月前
|
Python
python之数据的赋值方式,变量内存地址的获取方式,获取变量名的方法,不同方法之间的区别
python之数据的赋值方式,变量内存地址的获取方式,获取变量名的方法,不同方法之间的区别
|
数据采集 Python
[Python] 数据预处理(缺失值、异常值、重复值) [相关方法参数说明、代码示例、相关概念](二)
[Python] 数据预处理(缺失值、异常值、重复值) [相关方法参数说明、代码示例、相关概念](二)
C进阶:字符串相关函数及其模拟实现
C进阶:字符串相关函数及其模拟实现
52 0
C进阶:字符串相关函数及其模拟实现
|
JSON 数据格式 Python
如何判断返回的python字符串是否符合json格式
如何判断返回的python字符串是否符合json格式
|
JavaScript 前端开发
js传递参数时变量名动态拼接(含数字或指定规律的变量名称)
js传递参数时变量名动态拼接(含数字或指定规律的变量名称)
435 0