Object.assign-override вложенное свойство
У меня есть объект a
вроде этого:
const a = {
user: {
…
groups: […]
…
}
}
в результате чего в a.user
имеется намного больше свойств,
И я хотел бы изменить только значение a.user.groups
. Если я это сделаю:
const b = Object.assign({}, a, {
user: {
groups: {}
}
});
b
не имеет другого свойства кроме b.user.groups
, все остальные удаляются. Есть ли способ ES6 только изменить вложенное свойство, не теряя всего другого, с помощью Object.assign
?
Ответы
Ответ 1
После некоторых попыток я смог найти решение, которое выглядит довольно красиво:
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
}
}
Ответ 2
Вы можете изменить его таким образом,
const b = Object.assign({}, a, {
user: Object.assign({}, a.user, {
groups: {}
})
});
или просто сделайте,
const b = Object.assign({}, a);
b.user.groups = {};
Ответ 3
Метод Object.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, и если вы внесете какие-либо изменения в a, это будет отражено в b, и любые изменения в b не повлияют на
Ответ 4
Вы спросили, в частности, о ES6 с Object.assign, но, возможно, кто-то предпочтет мой более "общий" ответ - вы можете сделать это легко с lodash, и лично я считаю, что это решение более читаемо.
import * as _ from 'lodash';
_.set(a, 'user.groups', newGroupsValue);
Он мутирует объект.
Ответ 5
Маленькая точная мелодия Филлипса первый ответ.
const object1 = {
abc: {
a: 1
}
};
const object2 = {
abc: {
b: 2
}
};
Object.assign(object1, {
abc: {
...object1.abc,
...object2.abc
}
});
console.log(object1);
// Object { abc: Object { a: 1, b: 2 } }
Ответ 6
Здесь небольшая функция под названием Object_assign
(просто замените .
на _
, если вам нужно вложенное присваивание)
Функция устанавливает все целевые значения, либо вставляя туда исходное значение напрямую, либо рекурсивно вызывая Object_assign
снова, когда и целевое значение, и исходное значение являются объектами non- null
.
const target = {
a: { x: 0 },
b: { y: { m: 0, n: 1 } },
c: { z: { i: 0, j: 1 } },
d: null
}
const source1 = {
a: {},
b: { y: { n: 0 } },
e: null
}
const source2 = {
c: { z: { k: 2 } },
d: {}
}
function Object_assign (target, ...sources) {
sources.forEach(source => {
Object.keys(source).forEach(key => {
const s_val = source[key]
const t_val = target[key]
target[key] = t_val && s_val && typeof t_val === 'object' && typeof s_val === 'object'
? Object_assign(t_val, s_val)
: s_val
})
})
return target
}
console.log(Object_assign(Object.create(target), source1, source2))
Ответ 7
Более общее решение ниже. Это делает рекурсивное назначение, только если есть конфликты (те же имена ключей). Это решает проблемы назначения сложных объектов, которые имеют много опорных точек. Например, nested-object-assign
, существующий пакет для присвоения вложенных объектов в npm, застрял с назначением сложных объектов, потому что он рекурсивно проходит через все ключи.
var objecttarget = {
a: 'somestring',
b: {x:2,y:{k:1,l:1},z:{j:3,l:4}},
c: false
};
var objectsource = {
a: 'somestring else',
b: {k:1,x:2,y:{k:2,p:1},z:{}},
c: true
};
function nestedassign(target, source) {
Object.keys(source).forEach(sourcekey=>{
if (Object.keys(source).find(targetkey=>targetkey===sourcekey) !== undefined && typeof source[sourcekey] === "object") {
target[sourcekey]=nestedassign(target[sourcekey],source[sourcekey]);
} else {
target[sourcekey]=source[sourcekey];
}
});
return target;
}
// It will lose objecttarget.b.y.l and objecttarget.b.z
console.log(Object.assign(Object.create(objecttarget),objectsource));
// Improved object assign
console.log(nestedassign(Object.create(objecttarget),objectsource));