minjs1cn / weekly-learning

每周学习分享打卡
0 stars 0 forks source link

13 -【经典面试】深拷贝和浅拷贝 #13

Open wordlex opened 3 years ago

wordlex commented 3 years ago

什么是深拷贝、浅拷贝? 如何实现?

OceanApart commented 3 years ago

浅拷贝

对基本类型拷贝值,互不影响,对对象或数组只拷贝引用,无论修改新旧,两者都会发生变化。

深拷贝

对于对象完全拷贝一份,修改一个对象的属性也不会影响另一个。

function extend (deep, obj1, obj2) {
  // 默认浅拷贝
  var deep = false
  // 第一个参数
  var target = arguments[0] || {}
  // 待拷贝的参数遍历索引
  var i = 1
  // 参数个数
  var length = arguments.length
  // 待拷贝的键值
  var name
  // 待拷贝的对象
  var options
  // 目标值
  var src
  // 待拷贝值
  var copy
  // 新的 src 值
  var clone

  // 检查第一个参数类型,判断深浅拷贝
  if (typeof target === 'boolean') {
    deep = target
    target = arguments[1]
    i++
  }

  if (typeof target !== 'object' || !isFunction(target)) {
    // 如果目标不是对象或者函数则不能进行拷贝
    target = {}
  }

  for (; i < length; i++) {
    options = arguments[i]

    for (name in options) {
      src = target[name]
      copy = options[name]

      if (copy === target) {
        // 简单的循环引用判断
        continue
      }

      if (deep && copy && isPlainObject(copy) && (isPlainObject(copy) || (isCopyArray = Array.isArray(copy)))) {
        // 递归调用的对象必须是对象或者是数组

        if (isCopyArray) {
          // 如果复制的是数组,需要检查目标值是否为数组
          isCopyArray = false
          clone = src && Array.isArray(src) ? src : []
        } else {
          // 对象同理
          clone = src && isPlainObject(src) ? src : {}
        }

        // 深拷贝对象
        // target[name] 不能用 src 替代,src 只是一个指针
        target[name] = extend(deep, clone, copy)
      } else if (copy !== undefined) {
        // undefined 我们认为这个属性未定义/不需要,因此不需要复制
        // 其他类型直接复制
        target[name] = copy
      }
    }
  }

  return target
}

var a = { a: 1, b: 4 }
var b = { a: 1, b: [ 1, 2, 3] }

console.log(
  extend(true, a, b)
)