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

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

使用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)


目录
相关文章
|
6月前
|
设计模式 Rust JavaScript
【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数
【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数
84 0
|
2月前
|
前端开发 JavaScript
前端基础(十五)_时间对象、字符串对象
本文介绍了JavaScript中时间对象的操作方法,包括获取和设置年、月、日、小时、分钟、秒等,以及如何格式化时间显示,同时提及了字符串对象的常用方法。
30 0
前端基础(十五)_时间对象、字符串对象
ES6学习(3)模板字符串、简化对象和函数写法
ES6学习(3)模板字符串、简化对象和函数写法
|
5月前
|
JavaScript 前端开发
JavaScript进阶-模板字符串与增强的对象字面量
【6月更文挑战第19天】ES6的模板字符串和增强对象字面量提高了JavaScript的易读性和效率。模板字符串(` `)支持变量嵌入和多行,简化了字符串处理;增强对象字面量允许简写属性与方法,以及动态属性名。注意模板字符串的闭合和性能影响,以及对象字面量的简写语法和计算属性名的恰当使用。通过实例展示了这两项特性的应用,助力编写更优雅的代码。
102 4
|
6月前
02-python的基础语法-标识符/运算符/字符串拓展/字符串的拼接/字符串格式化/字符串精度控制/字符串格式化方式2/对表达式进行格式化/练习题/数据输入-input语句
02-python的基础语法-标识符/运算符/字符串拓展/字符串的拼接/字符串格式化/字符串精度控制/字符串格式化方式2/对表达式进行格式化/练习题/数据输入-input语句
LeetcodeSQL入门——知识点总结(选择/排序/修改/字符串处理/正则)
LeetcodeSQL入门——知识点总结(选择/排序/修改/字符串处理/正则)
|
JavaScript 前端开发
|
存储 JavaScript 前端开发
|
存储 JavaScript 前端开发