我有两个对象。一个是源对象,另一个是源对象的深层副本。每个中都存在相同的键,但深层副本可能具有与源对象不同的值。例如:
{
id: 123,
people: [{
name: "Bob",
age: 50
}, {
name: "Alice",
age: 40
}]
}
and
{
id: 123,
people: [{
name: "Bob",
age: 51 // bob is older now
}, {
name: "Alice",
age: 40
}]
}
请注意,对象更深入,有更多的键/对象/数组/值。
我想将更新的副本中的值(仅限值)应用回源对象。
重要的是我需要保持源对象的原始参考点。这意味着我无法执行以下任何操作:
sourceObject = updatedCopiedObject;
因为它会覆盖源对象并中断对源对象的引用
Object.assign(sourceObject, updatedCopiedObject);
因为,正如文档所说:
目标对象中的属性将被属性覆盖 如果他们有相同的密钥来源。后来的消息来源'属性会 同样地覆盖了之前的那些。
换句话说,它还会覆盖源对象的引用。
我需要做的就是Object.assign会做什么,但不覆盖属性 - 只需更改属性匹配的值。
我不知道任何内置方法,它将以必要的递归/深度方式执行此操作。我可以写一个方法,但我想先看看是否已经有解决这个问题的方法。
答案 0 :(得分:1)
您可以使用Object.entries()
迭代对象的属性和值作为数组的键值对。如果值是一个对象,则递归调用相同的函数来重新分配属性值,否则将值设置为源对象属性值
let source = {
id: 123,
people: [{
name: "Bob",
age: 50
}, {
name: "Alice",
age: 40
}]
}
let copy = {
id: 123,
people: [{
name: "Bob",
age: 51 // bob is older now
}, {
name: "Alice",
age: 40
}]
}
const reassign = (s, c) => {
for (let [key, prop] of Object.entries(c)) {
if (typeof prop !== "object") {
s[key] = prop;
} else {
reassign(s[key], prop)
}
}
return [s, c]
}
console.log(reassign(source, copy));

答案 1 :(得分:1)
我不知道任何内置方法会以必要的递归/深度方式执行此操作。我可以写一个方法,但我想先看看是否已经有解决这个问题的方法。
不,没有。
答案 2 :(得分:0)
您可以使用迭代和递归方法来分配值。
此提议会迭代源对象并在必要时创建新的目标属性,并在未找到嵌套对象时分配值。
function update(target, source) {
Object.keys(source).forEach(function(key) {
if (source[key] && typeof source[key] === 'object') {
return update(target[key] = target[key] || Array.isArray(source[key]) ? [] : {}, source[key]);
}
if (target[key] !== source[key]) {
target[key] = source[key];
}
});
}
var obj1 = { id: 123, people: [{ name: "Bob", age: 50 }, { name: "Alice", age: 40 }] }, obj2 = { id: 123, people: [{ name: "Bob", age: 51 }, { name: "Alice", age: 40 }] };
update(obj1, obj2);
console.log(obj1);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 3 :(得分:0)
guest271314的答案帮助我编写了一个递归解决方案,仅用于分配"值"从一个对象到另一个对象。对于我的应用程序,我需要更改它以处理对象中的数组:
assignObject (target = {}, source) {
let value = null
let keys = Object.keys(source)
for (let key of keys) {
value = source[key]
if (typeof value === 'object' && value !== null) {
if (Object.prototype.toString.call(value) === '[object Array]') {
target[key] = value
} else {
assignObject(target[key], value)
}
} else {
target[key] = value
}
}
return target
}