简体   繁体   English

javascript Object.assign() 没有覆盖字段

[英]javascript Object.assign() without overriding fields

Is there any way to merge two objects, like Object.assign(a, b) , but I want the same field in a keeps its origin value (without overriding from b ).有什么方法可以合并两个对象,例如Object.assign(a, b) ,但我希望a中的相同字段保持其原始值(不覆盖b )。

a = {x: 1, y: 2}
b = {y: 3, z: 4}

Object.assign(a, b)
// Now we get a = {x: 1, y: 3, z: 4}, so what if I want {x: 1, y: 2, z: 4}?
console.log(a) 

Note: thanks for the efforts from the answers, the key requirements for the question is:注意:感谢答案的努力,问题的关键要求是:

  1. modify a修改a
  2. not too much code没有太多的代码
  3. not too slow不太慢

To modify the a reference (like you seem to be wanting to do from your example), you could do:要修改a引用(就像您似乎想要从您的示例中所做的那样),您可以执行以下操作:

 const a = {x: 1, y: 2}; const b = {y: 3, z: 4}; Object.assign(a, {...b, ...a}); console.log(a);

This essentially says, replace the overlapping properties in b with those from a , and then merge this replaced object into a .这实质上是说,将b中的重叠属性替换为a中的属性,然后将这个替换的对象合并到a中。

Above, the {...b, ...a} first merges a with b , so a overwrites properties in b , giving us:上面, {...b, ...a}首先将ab合并,因此a覆盖b中的属性,给我们:

{y: 3, z: 4, x: 1, y: 2}
// evalutes to
{z: 4, x: 1, y: 2}

Now we merge this result into a with the Object.assign() call:现在我们使用Object.assign()调用将此结果合并到a

{x: 1, y: 2, z: 4, x: 1, y: 2}
// evalutes to
{z: 4, x: 1, y: 2}
// ie:
{x: 1, y: 2, z: 4}

Edit: To meet your requirements, use a regular for...in loop, it's efficient, doesn't require much code (especially if you remove the blocks), and modifies a :编辑:为了满足您的要求,请使用常规for...in循环,它很有效,不需要太多代码(特别是如果您删除了块),并修改a

 const a = {x: 1, y: 2}; const b = {y: 3, z: 4}; for(const key in b) a[key] ??= b[key]; console.log(a); // {"x": 1, "y": 2, "z": 4}

The above works if your values won't be nullish ( null / undefined ) as it uses logical nullish assignment ( ??= ), otherwise, you can replace the assignment with:如果您的值不会为空( null / undefined ),则上述方法有效,因为它使用逻辑空赋值( ??= ),否则,您可以将赋值替换为:

a[key] = key in a ? a[key] : b[key]; 

The best solution to this is to avoid using Object.assign and use spread operator as by doing so you'll achieve your goal with simple logic.对此的最佳解决方案是避免使用 Object.assign 并使用扩展运算符,因为这样做您将通过简单的逻辑实现您的目标。 In spread operator, the rightmost element overwrites the left one.在展开运算符中,最右边的元素会覆盖左边的元素。

a = {x: 1, y: 2};
b = {y: 3, z: 4};
        
result = {...b, ...a}; 
result2 = {...a, ...b};
console.log(result); // {x: 1, y: 2, z: 4} 
console.log(result2); // {x: 1, y: 3, z: 4} 

//if you don't want to create new object and just modify a then
Object.assign(a, {...b, ...a});
console.log(a); // {x: 1, y: 2, z: 4} 

 let a = { x: 1, y: 2 }; let temp = { ...a }; let b = { y: 3, z: 4 }; Object.assign(a, b); Object.assign(a, temp); console.log(a);

You could use Object.entries and filter out keys that are already in a .您可以使用Object.entries并过滤掉已经a .

eg.例如。

 a = {x: 1, y: 2} b = {y: 3, z: 4} //Object.assign(a, b) // Now we get a = {x: 1, y: 3, z: 4}, so what if I want {x: 1, y: 2, z: 4}? Object.assign(a, Object.fromEntries( Object.entries(b). filter(([k])=>!(k in a)))); console.log(a)

Finally I found the perfect solution is lodash.defaults .最后我发现完美的解决方案是lodash.defaults

https://lodash.com/docs/4.17.15#defaults https://lodash.com/docs/4.17.15#defaults

import _ from 'lodash'

a = {x: 1, y: 2}
b = {y: 3, z: 4}

_.defaults(a, b)

// Outputs {x:1, y:2, z:4}, perfectly as expected.
console.log(a) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM