为了账号安全,请及时绑定邮箱和手机立即绑定

理解JavaScript的深浅拷贝

标签:
JavaScript

一、深浅拷贝

// 目标数组
var targetArr = [10, 20, 30, [40, 50, 60]]

// 目标对象
var targetObj = {
  name: 'bobo',
  like: {
    eat: {
      fruit: 'Mango'
    },
    coding: 'js',
  },
  getName: function () {
    return this.name
  }
}

二、数组浅拷贝

2.1.第一种方法

使用数组的 concat 方法来实现:

var cloneTarget = [].concat(targetArr)

2.2.第二种方法

使用数组的 slice 方法来实现

var cloneTarget = targetArr.slice()

2.3.第三种方法

通过...展开运算符实现浅拷贝

var cloneTarget = [...targetArr]

三、对象浅拷贝

3.1.第一种方法

Object.assign(target, ...sources) 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。第一个参数是目标对象,第二个参数是一个或多个源对象。

代码实现:

var cloneTarget = Object.assign({}, targetObj)

3.2.第二种方法

通过...展开运算符实现浅拷贝

var cloneTarget = {...targetObj}

3.3.浅拷贝缺点

浅拷贝缺点:如果源对象的属性值是指向一个对象的引用,它也只是拷贝那个引用值。

console.log(cloneTarget.like.coding) // js
targetObj.like.coding = 'css' // 修改源对象的like属性对象
console.log(cloneTarget.like.coding) // css 拷贝的对象也变成了css

四、实现浅拷贝的方法

自己实现一个浅拷贝的方法,这个方法可以理解为前几个方法的原理,实际上就是根据传入的参数类型,创建一个对象或数组,然后将每个属性赋给新的对象或者数组:

function shallowCopy(obj) {
  // 判断是否为对象
  if (typeof obj !== 'object' || obj == null) {
    return obj
  }

  // 判断传入的对象是函数还是对象
  var newObj = obj instanceof Array ? [] : {}
  for (var key in obj) {
    // 只拷贝obj上的的属性
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key]
    }
  }

  return newObj
}

五、深拷贝

5.1.第一种方法

使用 JSON.parse(JSON.stringify(object)) 实现:

var deepClone = JSON.parse(JSON.stringify(targetObj))
var deepClone = JSON.parse(JSON.stringify(targetArr))

缺点:

  1. 会忽略 undefined
  2. 会忽略 symbol
  3. 不能序列化函数
  4. 不能解决循环引用的对象

5.2.自己实现深拷贝方法

在刚才实现的浅拷贝方法上,再判断一下属性值的类型,如果是对象,我们递归调用深拷贝函数即可:

function deepClone(obj) {
  // 判断是否为对象
  if (typeof obj !== 'object' || obj == null) {
    return obj
  }
  var newObj = obj instanceof Array ? [] : {}
  for (var key in obj) {
    // 只拷贝obj上的的属性
    if (obj.hasOwnProperty(key)) {
      // 如果属性值是对象,我们递归调用深拷贝函数
      newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
    }
  }
  return newObj
}

六、总结

类别 和源数据是否指向同一个对象 第一层为基本数据类型 源数据中包含子对象
赋值 改变原数据一同改变 改变原数据一同改变
浅拷贝 改变原数据不会一同改变 改变原数据一同改变
深拷贝 改变原数据不会一同改变 改变原数据不会一同改变
点击查看更多内容
5人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
4320
获赞与收藏
1744

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消