2

为什么会用到浅拷贝和深拷贝

首先来看一下如下代码

let a = b = 2
a = 3
console.log(a)
console.log(b)
let c = d = [1,2,3]
let e = f = {a:1,b:2,c:3}
c[0] = 2
e.a = 2
console.log(d[0])
console.log(f.a)

你会发现,同一个Array或者Object赋值给两个不同变量时,变量指向的是同一个内存地址,所以就会造成其中一个变量改变属性值,同时改变了另外一个变量的对应属性值。

而大多数实际项目中,我们想要的结果是两个变量(初始值相同)互不影响。所以就要使用到拷贝(分为深浅两种)

深浅拷贝的区别

浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。
浅拷贝有效性针对的是单一层级对象 [1,2,3]或者{a:1,b:2}
深拷贝有效性针对的是单层或者多层级对象 [1,2,3]或者{a:1,b:2}或者[1,[1],{a:1}]或者{a:[1],b:{c:2}}

浅拷贝

  • 如何实现
// 数组
let a = [1,2]
let b = a.slice()
// {}
let e = {a:[1],b:{d:1},2}
let f = Object.create(e)
function shallowCopy (obj) {
    if (typeof obj === 'object' && obj !== null) {
        if (Array.isArray(obj)) {
            return obj.slice()
        } else {
            let result = {}
            Object.keys(obj).forEach((item,i) = > {
                console.log(i)
                result[item] = obj[item]
            })
            return result
        }
    } else {
        return obj
    }
}
  • 应用场景
    对于一层结构的Array和Object想要拷贝一个副本时使用
    vue的mixin是浅拷贝的一种复杂型式

深拷贝

  • 如何实现
// 利用JSON(它能正确处理的对象是Number, String, Boolean, Array, 扁平对象)
let g = JSON.parse(JSON.stringify(obj))
// 适用于
function deepCopy (obj) {
  if (typeof obj === 'object' && obj !== null) {
    let objKeys = Object.keys(obj)
    let result
    if (Array.isArray(obj)) {
      result = []
    } else {
      if (obj.constructor === Object) {
        result = {}
      } else {
        return obj
      }
    }
    objKeys.forEach((item) => {
      if (typeof obj[item] === 'object' && obj[item] !== null) {
        switch (obj[item].constructor) {
          case Array:
            result[item] = deepCopy(obj[item])
            break
          case Object:
            result[item] = deepCopy(obj[item])
            break
          case Date:
            result[item] = new Date(obj[item])
            break
          case RegExp:
            let attributes = ''
            attributes += obj[item].global ? 'g' : ''
            attributes += obj[item].ignoreCase ? 'g' : ''
            attributes += obj[item].multiline ? 'g' : ''
            result[item] =  new RegExp(obj[item].source, attributes);
            break
          default:
            result[item] = obj[item]
            break
        }
      } else {
        result[item] = obj[item]
      }
    })
    return result
  } else {
    return obj
  }
}
  • 应用场景
    复制深层次的object数据结构
  • 对深拷贝的应用想法
    在实际工作中是不是用继承来实现更好?需要大家来讨论,提意见

孙小渃
459 声望17 粉丝

要想成为一个有智慧的人,你必须拥有多个模型。而且你必须将你的经验,无论是间接的还是直接的,都放到构成这些模型的网格上