深拷贝

深拷贝

1.JSON.parse(JSON.stringify(data))

/**
 * 深拷贝
 * @param data  传入数据,可为对象,也可为数组
 * @returns String  返回 
 */
const copyVueData = (data) => {
  var newData = null;
  if (Object.prototype.toString.call(data) == "[object Object]") {
    newData = data ? JSON.parse(JSON.stringify(data)) : {};
  } else if (Object.prototype.toString.call(data) == "[object Array]") {
    newData = data ? JSON.parse(JSON.stringify(data)) : [];
  } else if (Object.prototype.toString.call(data) == "[object String]") {
    newData = data ? JSON.parse(JSON.stringify(data)) : '';
  } else if (Object.prototype.toString.call(data) == "[object Number]") {
    newData = data ? JSON.parse(JSON.stringify(data)) : null;
  }
  return newData;
}

缺点:该方法不能解决属性为函数,undefined,循环引用的的情况

   

(1)原对象中的a、c不见了,undefined、function类型的key会丢失

(2)e时间对象,会变成字符串形式

(3)RegExp定义的属性会变成 {}

(4)NaN 类型会变成 null

(5)无法处理循环引用的问题

结论:这种拷贝方式局限性比较大,但是在日常开发中一般只是拷贝基本的数据类型,个人在开发中用的还是比较多

2.扩展运算符

利用了对象的结构赋值特性方法。

var arr = {
       name: '浪漫主义码农',
       age: 20,
       adress: ['jiangxi', 'changsha'],
       friends: {
           friend1: '张三',
           friend2: '李四'
       },
       function(){
           console.log("我是浪漫主义的对象")
       }
   }
   var brr={...arr}
   brr.name='法外狂徒张三'
   brr.adress[0]='长沙'
   console.log("arr为", arr)
   console.log("brr为", brr)

缺点:无对对象里面嵌套的对象进行深拷贝,相当于只是对一层引用对象进行深拷贝

3.递归深拷贝函数

通过递归实现深度拷贝,一般我们这样写

//使用递归实现深拷贝
   function clone(obj) {
       //判断拷贝的obj是对象还是数组
       var objClone = Array.isArray(obj) ? [] : {};
       if (obj && typeof obj === "object") { //obj不能为空,并且是对象或者是数组 因为null也是object
           for (key in obj) {
               if (obj.hasOwnProperty(key)) {
                   if (obj[key] && typeof obj[key] === "object") { //obj里面属性值不为空并且还是对象,进行深度拷贝
                       objClone[key] = clone(obj[key]); //递归进行深度的拷贝
                   } else {
                       objClone[key] = obj[key]; //直接拷贝
                   }
               }
           }
       }
       return objClone;
   }

优化递归深拷贝

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;
} 

结论:该方法可以解决深拷贝问题,但递归运行效率低,次数过多的话容易造成栈溢出。

 

posted @ 2022-04-25 10:58  时光独醒  阅读(10)  评论(0)    收藏  举报