js 深拷贝&浅拷贝

173 阅读1分钟

值和引用

js中的赋值方式分为值传递和引用传递

值传递

赋值过程只传递值,后者的变化不会影响前者

  • number -> 1
  • string -> 'a'
  • boolean -> true
  let x = 'x'
  let y = x
  y = 'y'

  console.log(x) // x
  console.log(y) // y

引用传递

赋值过程传递的是地址,后者的变化会更改前者

  • object -> {} , []
  let x = { name: 'x' }
  let y = x
  y.name = 'y'
  
  console.log(x) // {name:'y'}
  console.log(y) // {name:'y'}

浅拷贝

  • Object.assign() 完成浅拷贝
  let x = { name: 'x' }
  let y = Object.assign({}, x)
  y.name = 'y'
  console.log(x) // {name:'x'}
  console.log(y) // {name:'y'}
  • 当对象的属性也为引用传递类型时,则需要用 深拷贝
  let x = { name: 'x', other: { age: 12 } }
  let y = Object.assign({}, x)
  y.name = 'y'
  y.other.age = 100
  console.log(x) // {name:'x',other:{age:100}}
  console.log(y) // {name:'y',other:{age:100}}

深拷贝

JSON

  • 使用JSON.parse(JSON.stringify(x))
  let x = { name: 'x', other: { age: 12 } }
  let y = JSON.parse(JSON.stringify(x))
  y.name = 'y'
  y.other.age = 100
  console.log(x) // {name:'x',other:{age:12}}
  console.log(y) // {name:'y',other:{age:100}}

使用JSON的方法,无法转换function

let x = { name: 'x', other: { age: 12 }, getName() { } }
let y = JSON.parse(JSON.stringify(x))
y.name = 'y'
y.other.age = 100
console.log(x) // {name: "x", other: {age:12}, getName: ƒ}
console.log(y) // {name: "y", other: {age:100}}

Lodash

Lodash官网

  • 使用第三方工具类 完成深拷贝
let x = { name: 'x', other: { age: 12 }, getName() { } }
let y = _.cloneDeep(x)
y.name = 'y'
y.other.age = 100
console.log(x) // {name: "x", other: {age:12}, getName: ƒ}
console.log(y) // {name: "x", other: {age:100}, getName: ƒ}