继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

理解JavaScript的深浅拷贝

梁凤波
关注TA
已关注
手记 27
粉丝 4320
获赞 1744

一、深浅拷贝

// 目标数组
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
}

六、总结

类别 和源数据是否指向同一个对象 第一层为基本数据类型 源数据中包含子对象
赋值 改变原数据一同改变 改变原数据一同改变
浅拷贝 改变原数据不会一同改变 改变原数据一同改变
深拷贝 改变原数据不会一同改变 改变原数据不会一同改变
打开App,阅读手记
5人推荐
发表评论
随时随地看视频慕课网APP

热门评论

我在日常的业务代码中似乎浅拷贝用的多些,深拷贝有哪些应用场景呢?

查看全部评论