深拷贝浅拷贝(一行一行分析代码带你深入了解深浅拷贝)

前端工具代码详解(有防抖、节流等等常用工具解读)

第四章 深拷贝浅拷贝(一行一行分析代码带你深入了解深浅拷贝)


序言

所有的详细解析,都在代码的注释中。我建议大家做好看完后,自己思考一下,然后根据自己的感觉来写一遍,这样子可以加强自己的记忆,并且可以对比一下。感谢观看,期待点赞收藏关注,感谢读者。

一、浅拷贝一 (基础版)

代码如下

let obj1 = {
  a: 1,
  b: { a: 2, c: 5 },
}

let obj2 = {
  b: { a: 5, b: 3 },
  c: 4,
}
let obj3 = {
  d: 4,
}

// 初始版本
function extend1() {
  let nowData = arguments[0]
  for (i = 1; i < arguments.length; i++) {
    let options = arguments[i]
    if (options) {
      for (const key in options) {
        if (Object.hasOwnProperty.call(options, key)) {
          const element = options[key]
          nowData[key] = element
        }
      }
    }
  }
  return nowData
}

二、优化浅拷贝(提高了性能)

代码如下:

// 优化版本,将 element options name 都在外部创建,这样子就不用每一次循环都创建,只需要赋值
// 这样子效率更高
// 上述方法 需要 0.090ms ~ 0.12ms 左右 extend1
// 但是extend 只要0.067 ~ 0.072ms左右
function extend() {
  let name, options, copy
  let length = arguments.length
  // 因为 0 是目标对象,后续的都要放到 对象 0 里面
  // 所以 i = 1
  let i = 1
  // 存放目标对象,把后续都放到目的对象 target中 之后返回
  let target = arguments[0]
  for (; i < length; i++) {
    options = arguments[i]
    if (options != null) {
      // 因为都是对象,所以遍历对象
      for (name in options) {
        copy = options[name]
        if (copy !== undefined) {
          target[name] = copy
        }
      }
    }
  }
  return target
}

大家可以使用 console.time() 和 console.timeEnd()方法来看看效率,就可以看到使用的时间了

console.time()
let newObj = extend1(obj1, obj2, obj3)
console.timeEnd()
console.time()
let newObj = extend(obj1, obj2, obj3)
console.timeEnd()

三.升级版本(职场深拷贝,传递第一个参数为 true 就开启深拷贝,默认为浅拷贝,可以不传)

代码如下

var class2type = {}
var toString = class2type.toString
var hasOwn = class2type.hasOwnProperty

function isPlainObject(obj) {
  var proto, Ctor
  if (!obj || toString.call(obj) !== '[object Object]') {
    return false
  }
  proto = Object.getPrototypeOf(obj)
  if (!proto) {
    return true
  }
  Ctor = hasOwn.call(proto, 'constructor') && proto.constructor
  return (
    typeof Ctor === 'function' &&
    hasOwn.toString.call(Ctor) === hasOwn.toString.call(Object)
  )
}

function isFunction(obj) {
  return typeof obj === 'function'
}
// 升级版,根据第一个参数,确定要不要深拷贝
function extend2() {
  // 默认不要深拷贝(深拷贝性能消耗大)因为要递归
  let deep = false
  let name, options, src, copy, clone, copyIsArray
  let length = arguments.length
  // 如果第一个值没有传递 deep 的值,就从 1 开始循环
  let i = 1
  // 获取第一个值
  let target = arguments[0]
  // 如果第一个值传递了deep
  if (typeof target === 'boolean') {
    deep = target
    target = arguments[1] || {}
    i++
  }
  // 如果target不是对象,无法进行复制,函数是可以复制的,所以要判断
  // 不是对象 也不是函数的时候,给target赋值为{}
  if (typeof target !== 'object' && !isFunction(target)) {
    target = {}
  }
  // 循环遍历对象
  for (; i < length; i++) {
    // 获取当前对象
    options = arguments[i]
    if (options != null) {
      for (name in options) {
        // 目标属性值,假设如果target[name] 是对象,并且要深拷贝就需要使用
        src = target[name]
        copy = options[name]
        // 防止循环引用
         if (target === copy) {
          continue
        }
        // 判断 src 的数据类型 和 copy的类型是否一致
        // 如果不一致,转换为相同的类型
        if (
          deep &&
          copy &&
          (isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))
        ) {
          if (copyIsArray) {
            copyIsArray = false
            clone = src && Array.isArray(src) ? src : []
          } else {
            clone = src && isPlainObject(src) ? src : {}
          }
          target[name] = extend(deep, clone, copy)
        } else if (copy !== undefined) {
          target[name] = copy
        }
      }
    }
  }
  return target
}

总结

以上就是关于深拷贝和浅拷贝的实现方法了,大家可以仔细观看,最好看完后,自己敲一遍,不要看着代码敲,根据自己的想法写。最后感谢观看,希望大家一起变强!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值