zoukankan      html  css  js  c++  java
  • js 对象拷贝的三种方法,深拷贝函数。

    js 对象拷贝的三种方法

    以下面数据格式obj 为主:

      const obj = {
        data: 1,
        un: undefined,
        info: {
          d: 2
        },
        fn: function() {
          console.log('Function')
        },
        get c() {
          return info.d
        }
      }
    

    Object.assign

    const ObjA = Object.assign({}, obj)
    ObjA.data = 'a'
    ObjA.info.d = 'b'
    
    const ObjB = Object.assign({}, obj)
    ObjB.data = 'c'
    ObjB.info.d = 'd'
    
    console.log(ObjA)
    console.log(ObjB)
    /* 
    ==========输出==========
    { data: 'a', info: { d: 'd' }, un: undefined, fn: [Function: fn] }
    { data: 'c', info: { d: 'd' }, un: undefined, fn: [Function: fn] }
    */
    

    我们会发现info.d 内容相等,说明Object.assign无法拷贝深层次内容,适用于浅层拷贝。

    JSON.stringify & JSON.parse

    const ObjA = JSON.parse(JSON.stringify(obj))
    ObjA.data = 'a'
    ObjA.info.d = 'b'
    
    const ObjB = JSON.parse(JSON.stringify(obj))
    ObjB.data = 'c'
    ObjB.info.d = 'd'
    console.log(ObjA)
    console.log(ObjB)
    
    /* 
    ==========输出==========
    { data: 'a', info: { d: 'b' }, c: 2 }
    { data: 'c', info: { d: 'd' }, c: 2 }
    */
    

    我们将源对象转换为字符串,再转换为新对象虽然解决了深层次拷贝的问题,但我们会发现对象中的Functionundefined 无法拷贝,并且将c: [Getter] 直接转换成了键值对 c:2。

    Object.create

    const ObjA = Object.create(obj)
    ObjA.data = 'a'
    ObjA.info.d = 'b'
    
    const ObjB = Object.create(obj)
    ObjB.data = 'c'
    ObjB.info.d = 'd'
    
    console.log(ObjA)
    console.log(ObjB)
    console.log(ObjA.__proto__)
    console.log(ObjB.__proto__)
    /* 
    ==========输出==========
    { data: 'a' }
    { data: 'c' }
    { data: 1, info: { d: 'd' }, fn: [Function: fn], c: [Getter] }
    { data: 1, info: { d: 'd' }, fn: [Function: fn], c: [Getter] }
    */
    

    Object.create 原型链继承,也可以达到内容浅层拷贝。

    总结:

    赋值 浅层拷贝 深层拷贝 getter/setter
    Object.assign ok no no
    JSON.stringify ok ok no
    Object.create ok no ok

    深拷贝函数

    
    function checkType(any) {
      return Object.prototype.toString.call(any).slice(8, -1)
    }
    function clone(any){
      if(checkType(any) === 'Object') { // 拷贝对象
        let o = {};
        for(let key in any) {
          o[key] = clone(any[key])
        }
        return o;
      } else if(checkType(any) === 'Array') { // 拷贝数组
        var arr = []
        for(let i = 0,leng = any.length;i<leng;i++) {
          arr[i] = clone(any[i])
        }
        return arr;
      } else if(checkType(any) === 'Function') { // 拷贝函数
        return new Function('return '+any.toString()).call(this)
      } else if(checkType(any) === 'Date') { // 拷贝日期
        return new Date(any.valueOf())
      } else if(checkType(any) === 'RegExp') { // 拷贝正则
        return new RegExp(any)
      } else if(checkType(any) === 'Map') { // 拷贝Map 集合
        let m = new Map()
        any.forEach((v,k)=>{
          m.set(k, clone(v))
        })
        return m
      } else if(checkType(any) === 'Set') { // 拷贝Set 集合
        let s = new Set()
        for(let val of any.values()) {
          s.add(clone(val))
        }
        return s
      }
      return any;
    }
    // 测试
    
    var a = {
      name: '张三',
      skills: ['踢球', '跑步', '打羽毛球'],
      age: 18,
      love: {
        name: '小红',
        age: 16
      },
      map: new Map([['aaa', '123']]),
      fn:function(a){
        console.log(`我的名字叫${this.name}` + a)
      },
      set: new Set([1,2,3,4,5])
    }
    var newA = clone(a)
    a.age = 100
    a.love.age = 100
    a.set.add('1123')
    a.skills.push('计算机')
    a.name = '小梅'
    a.map.set('name', '小明')
    
    console.log(a)
    console.log(newA)
    
    a.fn('a')
    newA.fn('newA')
    
  • 相关阅读:
    如何设置路由器实现静态IP配置
    linux内核源码结构
    linux源码“.config”文件分析
    用python来调试网络程序
    dbm速算
    用python虚拟串口
    sed学习笔记
    贴一段shell代码
    ethtool使用记录
    mint锁屏设置
  • 原文地址:https://www.cnblogs.com/wangyong1997/p/13577725.html
Copyright © 2011-2022 走看看