Skip to content

实现浅拷贝和深拷贝 #13

@lfb

Description

@lfb

浅拷贝

Object.assign 只会拷贝所有的属性值到新的对象中,如果属性值是对象的话,拷贝的是地址,所以并不是深拷贝。

let a = {
  age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1

另外我们还可以通过展开运算符 ... 来实现浅拷贝

let a = {
  age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1

深拷贝

JSON.parse(JSON.stringify(object)) 来解决

let a = {
  age: 1,
  jobs: {
    first: 'FE'
  }
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE

缺点:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象

实现深拷贝

function deepClone(obj) {
  // 判断传入的参数是否为对象
  function isObject(o) {
    return (typeof o === 'object' || typeof o === 'function') && o !== null
  }

  if (!isObject(obj)) {
    return obj
  }

  var newObj = isObject(obj) ? {} : []

  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 每次递归调用的函数都是全新的上下文
      newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    }
  }

  return newObj
}

ES6语法实现

@作者:yck

function deepClone(obj) {
  function isObject(o) {
    return (typeof o === 'object' || typeof o === 'function') && o !== null
  }

  if (!isObject(obj)) {
    throw new Error('非对象')
  }

  let isArray = Array.isArray(obj)
  let newObj = isArray ? [...obj] : { ...obj }
  Reflect.ownKeys(newObj).forEach(key => {
    newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
  })

  return newObj
}

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions