深拷贝与浅拷贝初识

目录

浅拷贝

如何简易高效的实现浅拷贝

深拷贝


浅拷贝

什么是浅拷贝?

只把对象上第一层的属性拷贝一份, 放到一个新对象上

如果浅拷贝的属性指向的是一个对象或者一个数组, 那么它拷贝的是这个对象或数组的内存地址 

 浅拷贝代码演示: 

    // 浅拷贝:只把对象上第一层的属性拷贝一份,放到一个新对象上!!!
    function simpleCopy(obj) {
      // 通过 "Array.isArray()"方法 判断用户传进来的 obj 是“数组”还是“真正的对象”
      const newObj = Array.isArray(obj) ? [] : {}

      // 循环对象上的每个属性,进行浅拷贝
      for (let k in obj) {
        newObj[k] = obj[k]
      }

      // 返回拷贝的结果
      return newObj
    }

一般情况下浅拷贝时是不需要拷贝原型上的属性的

for(... in ...) {} 会拷贝原型上的属性,此时需要增加一个判断, 通过 对象.hasOwnProperty('属性')方法判断, 如果当前属性是通过继承得来的,那么就不拷贝

对象/数组.hasOwnProperty('属性') :

返回一个布尔值

当返回值为true时, 表示当前属性是该 对象/数组 本身的属性,不是继承的属性

当返回值为false是时, 表示当前属性是 继承的属性

代码实现:

  <script>
    const o = {
      name: 'zs',
      info: {
        city: '北京',
        area: '顺义区'
      }
    }

    o.__proto__ = {
      a: 10,
      b: 20
    }

    // 浅拷贝:只把对象上第一层的属性拷贝一份,放到一个新对象上!!!
    function simpleCopy(obj) {
      // 要判断用户传进来的 obj 是“数组”还是“真正的对象”
      const newObj = Array.isArray(obj) ? [] : {}

      // 循环对象上的每个属性,进行浅拷贝
      for (let k in obj) {
        if (obj.hasOwnProperty(k)) {
          newObj[k] = obj[k]
        }
      }

      // 返回拷贝的结果
      return newObj
    }

    const o2 = simpleCopy(o)
    console.log(o2)

  </script>

详解:

 for ...in ... 循环会循环到继承过来的属性
 for (let k in o) {
   // 调用 对象.hasOwnProperty() 方法,可以判断指定的属性是继承过来的,还是我本身就有
   // 如果 hasOwnProperty() 返回值是 true,证明这个属性是自己的,不是继承的
   // 如果 hasOwnProperty() 返回值是 false,证明这个属性是继承过来的
   // o.hasOwnProperty('属性')
   if (o.hasOwnProperty(k)) {
     console.log(k, o[k])
   }
 }

如何简易高效的实现浅拷贝

实际开发中的方法:

1. Object.assign(要拷贝的, 被拷贝的)

2. 展开运算符 ...

方案一:

const o = {
  name: 'zs',
  info: {
    city: '北京',
    area: '顺义区'
  }
}
const o2 = {}
// 实现对象浅拷贝的方法
Object.assign(o2, o)
console.log(o2.info === o.info)
const arr = [1, 2, { name: 'zs' }]
const arr2 = []
// Object.assign 可以对数组实现浅拷贝
Object.assign(arr2, arr)
console.log(arr2[2] === arr[2])

方案二: 

const o = {
  name: 'zs',
  info: {
    city: '北京',
    area: '顺义区'
  }
}
const o2 = {
  // 展开运算符
  ...o
}
console.log(o2.info === o.info)
const arr = [1, 2, { name: 'zs' }]
const arr2 = [...arr]
console.log(arr2[2] === arr[2])

深拷贝

基于浅拷贝再做一次判断, 如果当前循环的值是对象类型, 那么再次调用方法,  这样就形成了递归

凡是遇到当前的值是对象类型就对当前的值再做一次浅拷贝 

代码演示:  

<script>
    const o = {
      name: 'zs',
      info: {
        city: '北京',
        area: '顺义区'
      }
    }

    // 深拷贝的方法
    function deepCopy(obj) {
      const newObj = Array.isArray(obj) ? [] : {}

      for (let k in obj) {
        if (obj.hasOwnProperty(k)) {
          // 如果当前属性的值是对象类型,则需要进一步做浅拷贝的操作
          if (typeof obj[k] === 'object') {
            newObj[k] = deepCopy(obj[k])
          } else {
            newObj[k] = obj[k]
          }
        }
      }

      return newObj
    }

    const o2 = deepCopy(o)
    console.log(o2.info === o.info)
  </script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值