1. 程式人生 > 實用技巧 >js 物件拷貝的三種方法

js 物件拷貝的三種方法

js 物件拷貝的三種方法

以下面資料格式obj 為主:

  const obj = {
    data: 1,
    un: undefined,
    info: {
      d: 2
    },
    fn: function() {
      console.log('Function')
    },
    get c() {
      return info.d
    }
  }

Object.assign

const ObjA = Object.assign({}, obj)
ObjA.data = 'a'
ObjA.info.d = 'b'

const ObjB = Object.assign({}, obj)
ObjB.data = 'c'
ObjB.info.d = 'd'

console.log(ObjA)
console.log(ObjB)
/* 
==========輸出==========
{ data: 'a', info: { d: 'd' }, un: undefined, fn: [Function: fn] }
{ data: 'c', info: { d: 'd' }, un: undefined, fn: [Function: fn] }
*/

我們會發現info.d 內容相等,說明Object.assign無法拷貝深層次內容,適用於淺層拷貝。

JSON.stringify & JSON.parse

const ObjA = JSON.parse(JSON.stringify(obj))
ObjA.data = 'a'
ObjA.info.d = 'b'

const ObjB = JSON.parse(JSON.stringify(obj))
ObjB.data = 'c'
ObjB.info.d = 'd'
console.log(ObjA)
console.log(ObjB)

/* 
==========輸出==========
{ data: 'a', info: { d: 'b' }, c: 2 }
{ data: 'c', info: { d: 'd' }, c: 2 }
*/

我們將源物件轉換為字串,再轉換為新物件雖然解決了深層次拷貝的問題,但我們會發現物件中的Functionundefined 無法拷貝,並且將c: [Getter] 直接轉換成了鍵值對 c:2。

Object.create

const ObjA = Object.create(obj)
ObjA.data = 'a'
ObjA.info.d = 'b'

const ObjB = Object.create(obj)
ObjB.data = 'c'
ObjB.info.d = 'd'

console.log(ObjA)
console.log(ObjB)
console.log(ObjA.__proto__)
console.log(ObjB.__proto__)
/* 
==========輸出==========
{ data: 'a' }
{ data: 'c' }
{ data: 1, info: { d: 'd' }, fn: [Function: fn], c: [Getter] }
{ data: 1, info: { d: 'd' }, fn: [Function: fn], c: [Getter] }
*/

Object.create 原型鏈繼承,也可以達到內容淺層拷貝。

總結:

賦值 淺層拷貝 深層拷貝 getter/setter
Object.assign ok no no
JSON.stringify ok ok no
Object.create ok no ok