Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object & Array 的深拷贝 #37

Open
Popxie opened this issue Aug 24, 2021 · 0 comments
Open

Object & Array 的深拷贝 #37

Popxie opened this issue Aug 24, 2021 · 0 comments
Assignees

Comments

@Popxie
Copy link
Owner

Popxie commented Aug 24, 2021

Object & Array 的深拷贝

首先看个例子:

let a = { name: '张三' }
let b = a
b.name = '李四'
console.log('a:', a) // 李四
console.log('b:', b) // 李四

var a = [1, 2, 3]
var b = a
b.push(4)
console.log('a:', a) //1,2,3,4
console.log('b:', b) //1,2,3,4

因为在 JavaScript 中,对象跟数组属于引用数据类型,指针都会指向同一个,所以一改都改.
如何各改各的呢?(深拷贝)

方法一 (拓展运算符,只深拷贝第一层)

let a = { name: '张三' }
let b = { ...a }
b.name = '李四'
console.log('a:', a) // {name: "张三"}
console.log('b:', b) // {name: "李四"}

let a = [1, 2]
let b = [...a]
b[1] = 3
console.log('a:', a) // [1, 2]
console.log('b:', b) // [1, 3]

方法二 (JSON.parse(JSON.stringify()))

let a = { name: '张三' }
let b = {}
b = JSON.parse(JSON.stringify(a))
b.name = '李四'
console.log('a:', a) // {name: "张三"}
console.log('b:', b) // {name: "李四"}

let a = [1, 2]
let b = []
b = JSON.parse(JSON.stringify(a))
b[1] = 3
console.log('a:', a) // [1,2]
console.log('b:', b) // [3]

缺点

  • 正则会被处理为空对象
  • 具备函数/symbol/undefined 属性值直接被干掉
  • BigInt 还处理不了,会报错 // Uncaught TypeError: Do not know how to serialize a BigInt
  • 日期对象最后还是字符串
let obj = {
  a:1,
  b:/^$/,
  c:undefined,
  d:new Date()
}
console.log(JSON.parse(JSON.stringify(obj)))
// 结果如下
{
  a:1,
  b:{},
  d:"2020-11-20T07:04:10.653Z"
}

方法三 (自定义函数方法)

function deepCopy(param) {
  if (!param) return param

  if (param instanceof Date) return new Date(param)
  
  if (param instanceof RegExp) return new RegExp(param)

  // 数组和对象都会被判断为 'object'
  if (typeof param !== "object") return param

  // const blankArrOrObj = param instanceof Array ? [] : {}
  // 或者
  const blankArrOrObj = Array.isArray(param) ? [] : {}

  // tips: for in 如果是数组那么就是 (index in arr) 如果是 对象 则就是 (key in obj)
  for (const keyOrIndex in param) {
    blankArrOrObj[keyOrIndex] = typeof param[keyOrIndex] === 'object' 
      ? deepCopy(param[keyOrIndex]) 
      : param[keyOrIndex]
  }
  return blankArrOrObj
}

// 对象
let a = { name: '张三' }
b = deepCopy(a)
b.name = '李四'
console.log('a:', a) // {name: "张三"}
console.log('b:', b) // {name: "李四"}

// 简单数组
let a = [1, 2]
b = deepCopy(a)
b[1] = 3
console.log('a:', a) // [1,2]
console.log('b:', b) // [3]

// 对象数组
let a = [{ name: 'x'}, { name: 'y' }]
b = deepCopy(a)
b[1].name =  'z'
console.log('a:', a) // [{ name: 'x'}, { name: 'y' }]
console.log('b:', b) // [{ name: 'x'}, { name: 'z' }]

深拷贝的终极探索·掘金
浅拷贝与深拷贝·掘金

@Popxie Popxie self-assigned this Aug 24, 2021
@Popxie Popxie closed this as completed Aug 24, 2021
@Popxie Popxie changed the title 【占位issue】 Object & Array 的深拷贝 Feb 7, 2022
@Popxie Popxie reopened this Feb 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant