js对象的复制方法

js对象复制

对象是js里重要的基本类型,广义上讲js里万物皆对象。复制一个数据,是一个常用的需求,但是相对于基本数据类型如数字,字符串等,对象复制起来要复杂的多。

// 数字的复制
var m = 666
var n = m
console.log(n) // 666
复制代码

对象的复制是无法这样的,以为这样的复制只是复制了对象的引用

var o1 = {
  m: 666,
  n: 'abc'
}
var o2 = o1
console.log(o2.m) // 666
console.log(o2.n) // abc
// 改变o1会导致o2也发生改变
o1.m = 999
o1.n = 'def'
console.log(o2.m) // 999
console.log(o2.n) // def
复制代码

可以看出,当原对象发生改变,复制的对象也会发生改变,这不符合我们的要求。

下面我将介绍3种复制对象的方法:

  1. 使用递归遍历对象的所有可枚举属性然后复制
var copy_1 = function (obj) {
  var o
  // 检测传入数据的属性,根据数据的类型分别处理
  switch (typeof(obj)) {
    case 'undefined':
      break
    case 'string':
      o = obj + ''
      break
    case 'number':
      o = obj - 0
      break
    case 'boolean':
      o = !!obj
      break
    case 'object':
      if (obj === null) {
        o = null
      } else {
        if (Object.prototype.toString.call(obj).slice(8, -1) === 'Array') {
          o = []
          for (let v of obj) {
            o.push(copy_1(v))
          }
        } else {
          o = {}
          // 遍历对象,并递归遍历对象每一层,然后复制每层属性
          for (let v in obj) {
            o[v] = copy_1(obj[v])
          }
        }
      }
      break
    default:
      o = obj
  }
  return o
}

var o1 = {
  m: 666,
  n: 'abc'
}
var o2 = copy_1(o1)
o1.m = 123
console.log(o1.m) // 123
console.log(o2.m) // 666
复制代码

此方法不可复制对象的getter和setter属性,不可枚举属性

  1. 使用es6里的Object.assign方法
var copy_2 = function (obj) {
  var o
  if (Object.prototype.toString.call(obj).slice(8, -1) === 'Array') {
    o = []
  } else {
    o = {}
  }
  // 使用Object.assign()
  return Object.assign(o, obj)
}

var o1 = {
  m: 666,
  n: 'abc'
}
var o2 = copy_2(o1)
o1.m = 123
console.log(o1.m) // 123
console.log(o2.m) // 666
复制代码

此方法不可复制对象的getter和setter属性,不可枚举属性,对象的继承属性

  1. 使用getOwnPropertyDescriptors和defineProperties
var copy_3 = function (obj) {
  var o = {}
  // 获取原对象所有属性的描述
  var des = Object.getOwnPropertyDescriptors(obj)
  // 通过对象属性描述创建新对象
  Object.defineProperties(o, des)
  return o
}

var o1 = {
  m: 666,
  n: 'abc'
}
var o2 = copy_3(o1)
o1.m = 123
console.log(o1.m) // 123
console.log(o2.m) // 666
复制代码

此方法不可复制对象的继承属性

以上三种方法各有各的适用范围,为了达到各种复制需求,可以考虑综合几种方法来达到复制的要求。

转载于:https://juejin.im/post/5c9da9a16fb9a070e552ac7c

你可能感兴趣的:(js对象的复制方法)