(五) js中的深浅拷贝

无论是深拷贝还是浅拷贝都是创建一个新的对象

1. 浅拷贝

浅拷贝是创建一个新对象, 这个对象有原始对象属性值的一份精确拷贝. 如果属性是基本类型, 拷贝的就是基本类型的值, 如果属性时引用类型, 拷贝的就是内存地址

function shallow(obj) {

  if (typeof obj !== 'object' || obj === null) return obj

  var shallowObj = {}
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      shallowObj[i] = obj[i]
    }
  }
  return shallowObj
}

var person = {
  name: '张三',
  age: 18,
  hobbies: ['唱歌', ['打游戏', '看电影']]
}

var p = shallow(person)

p.name = '李四'
p.hobbies[0] = '跳舞'

console.log('p: ', p);
console.log('person: ', person);

2. 深拷贝

深拷贝是将一个对象从内存中完整的拷贝一份出来, 从堆内存中开辟一个新的区域存放新对象, 彼此完全独立

function deepClone(obj) {
  var cloneObj = {}

  if (typeof obj !== 'object' || obj === null) return obj

  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      cloneObj[i] = deepClone(obj[i])
    }
  }

  return cloneObj
}

var person = {
  name: '张三',
  age: 18,
  hobbies: ['唱歌', ['打游戏', '看电影']]
}

var p = shallow(person)

p.name = '李四'
p.hobbies[0] = '跳舞'

console.log('p: ', p);
console.log('person: ', person);

但是上面的深拷贝还有一个问题, 那就是对于 Date、RegExp这两个对象是无法进行拷贝的

var a = deepClone({ date: new Date() })
console.log(a);

因此我们需要完善一下

function deepClone(obj) {
  var cloneObj = {}
  
  // 添加如下两行判断
  if (obj instanceof Date) return new Date()
  if (obj instanceof RegExp) return new RegExp()
  
  if (typeof obj !== 'object' || obj === null) return obj

  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      cloneObj[i] = deepClone(obj[i])
    }
  }

  return cloneObj
}

3. 总结对比

是否和原始值指向同一对象 第一层数据为基本类型 第一层数据为引用类型
赋值(复制) 改变会使原始值一同改变 改变会使原始值一同改变
浅拷贝 不是 不会改变原始值 改变会使原始值一同改变
深拷贝 不是 不会改变原始值 不会改变原始值
posted @ 2021-07-26 14:11  只猫  阅读(104)  评论(0编辑  收藏  举报