浅拷贝和拷贝的概念和实现

一.从简单类型和复杂类型数据的存储来认识深拷贝

在这里插入图片描述在这里插入图片描述

二.区分常用操作是深拷贝还是浅拷贝:
1.= 赋值

不论是简单的对象或数组还是复杂的对象或数组,都是浅拷贝

以简单数组示例:
let arr = [1, 2, 3]
let newArr = arr
newArr[0] = 0
console.log(arr[0]) // 0
2.循环赋值

简单的对象或数组可以实现深拷贝,复杂的对象或数组,内部的复杂类型数据是浅拷贝

以对象示例:
let obj = {
  key1: 1,
  key2: [1, 2, 3]
}
let newArr = {}
for (let i in obj) {
  newArr [i] = obj[i]
}
newArr.key1 = 0
newArr.key2[0] = 0
console.log(arr.key1) // 1 简单类型数据实现了深拷贝
console.log(arr.key2[0]) // 0 复杂类型数据是浅拷贝

注意:如果直接将复杂数据类型整体替换,则互不影响
newArr.key2 = []
console.log(arr.key2) // [1, 2, 3]
3.Object.assign(newObj, obj)(ES6)和循环赋值相同
三.深拷贝实现
1.不含函数的对象可以使用JSON.parse()和JSON.stringify()进行深拷贝(函数键值对会忽略)
let obj = {
  key1: 1,
  key2: {
    key2_key1: 2
  }
}
let newObj = {}
newObj = JSON.parse(JSON.stringify(obj))
newObj.key1 = 0
newObj.key2.key2_key1 = 0
console.log(obj.key1) // 1
console.log(obj.key2.key2_key1) // 2
2.循环递归

对象的属性值不会引用外层对象的情况(否则会进入死循环):

function deepCopy(obj) {
  let newObj = Array.isArray(obj) ? [] : {}
  if (obj && typeof obj === "object") {
    for (var i in obj) {
      if (obj.hasOwnProperty(i)) {
        // 如果子属性为引用数据类型,递归复制
        if (obj[i] && typeof obj[i] === "object") {
          newObj[i] = deepCopy(obj[i])
        } else {
          // 如果是基本数据类型,只是简单的复制
          newObj[i] = obj[i]
        }
      }
    }
  }
  return newObj 
}
deepClone (obj) {
    var _obj
    if (typeof obj === 'object' && obj !== null) {
      // object
      if (Object.prototype.toString.call(obj) === '[object Object]') {
        _obj = {}
        for (var key in obj) {
          _obj[key] = deepClone(obj[key])
        }
        return _obj
      } else if (Object.prototype.toString.call(obj) === '[object Array]') { // Array
        _obj = []
        for (var _key in obj) {
          _obj[_key] = deepClone(obj[_key])
        }
        return _obj
      } else {
        return obj
      }
    } else {
      return obj
    }
  }

包含对象的属性值引用外层对象的情况:

function deepCopy(obj) {
      var newObj = Array.isArray(obj) ? [] : {}
      if (obj && typeof obj === "object") {
        for (leti in obj) {
          let prop = obj[i]  // 避免相互引用造成死循环,如obj.a=obj
          if (prop == obj) {
            continue
          }
          if (obj.hasOwnProperty(i)) {
            //  如果子属性为引用数据类型,递归复制
            if (prop && typeof prop === "object") {
              newObj[i] = (prop.constructor === Array) ? [] : {}
              arguments.callee(prop, newObj[i])  // 递归调用
            } else {
              // 如果是基本数据类型,只是简单的复制
              newObj[i] = prop
            }
          }
        }
      }
      return newObj
    }

参考:
一篇文章彻底说清JS的深拷贝/浅拷贝https://segmentfault.com/a/1190000012828382
JS深拷贝和浅拷贝的实现https://www.jianshu.com/p/cf1e9d7e94fb

猜你喜欢

转载自blog.csdn.net/qq_37246828/article/details/89475028
今日推荐