2017-01-11 116 views
10

我有一個對象a這樣的:Object.assign重寫的嵌套屬性

const a = { 
    user: { 
    … 
    groups: […] 
    … 
    } 
} 

,其中有很多更多的屬性在a.user

而且我想只改變a.user.groups值。如果我這樣做:

const b = Object.assign({}, a, { 
    user: { 
    groups: {} 
    } 
}); 

b沒有任何其他物業,除了b.user.groups,所有其他人都將被刪除。有沒有任何ES6的方式來改變嵌套屬性,而不會丟失所有其他的,Object.assign

+2

它看起來在做'Object.assign'應該做的事情。它正在改變你提供的新對象的'用戶'屬性。如果它是你想改變的唯一的東西,你爲什麼不簡單地做'b.user.groups =/* value * /'? – taguenizy

回答

23

經過一番努力,我能找到一個解決方案,看起來相當不錯的那樣:

const b = Object.assign({}, a, { 
    user: { 
    ...a.user, 
    groups: 'some changed value' 
    } 
}); 

爲了讓這個答案在這裏更完整的一個小提示:

const b = Object.assign({}, a) 

本質上是一樣的:

const b = { ...a } 

,因爲它只是將所有的a...a)的屬性,以一個新的對象。因此上述罐寫成:

const b = { 
    ...a,   //copy everything from a 
    user: {  //override the user property 
     ...a.user, //same sane: copy the everything from a.user 
     groups: 'some changes value' //override a.user.group 
    } 
} 
6

你可以改變這種方式,

const b = Object.assign({}, a, { 
    user: Object.assign({}, a.user, { 
      groups: {} 
     }) 
}); 

或只是做,

const b = Object.assign({}, a); 
b.user.groups = {}; 
+2

不會變異'b.user.groups','用戶'在b和a!之間共享。 – borovsky

3

的Object.assign()方法被用於從一個或多個源對象中所有可枚舉自己的屬性的值複製到目標對象。它會返回目標對象。

assign方法將通過從源對象複製來創建一個新對象,如果稍後在源對象中更改任何方法,它將不會反映到新對象。

使用create()

的的Object.create()方法創建具有指定原型對象和屬性的新對象。

const b = Object.create(a) 
b.user.groups = {} 
// if you don't want the prototype link add this 
// b.prototype = Object.prototype 

這種方式,你已經b。通過原型鏈接到,如果你做的是將在B反映的任何變化,並在B的任何變化都不會影響一個

+0

這確實是一個有趣的觀點,但在這種情況下,我需要創建一個源的副本。 – philipp

+0

然後你自己的回答就是你要找的 –

+0

或者使用create()然後做。 b.prototype = Object.prototype –

3

你問特別是對於使用Object.assign的ES6方式,但也許其他人會喜歡我的'一般'答案 - 你可以輕鬆地用lodash來做到這一點,並且我個人認爲這個解決方案更具可讀性。

import * as _ from 'lodash'; 
_.set(a, 'user.groups', newGroupsValue); 

它改變對象。

+0

也許,但它需要另一個庫... – philipp

+1

當然,這就是爲什麼我認爲你不想使用我的解決方案,但其他有類似問題的人可能會覺得它有用。 –