(_.merge in ES6/ES7)Object.assign 不覆盖未定义的值

Posted

技术标签:

【中文标题】(_.merge in ES6/ES7)Object.assign 不覆盖未定义的值【英文标题】:(_.merge in ES6/ES7)Object.assign without overriding undefined values 【发布时间】:2017-02-19 23:49:59 【问题描述】:

lodash 中有_.merge 功能。我想在 ES6 或 ES7 中实现同样的目标。

有这个sn-p:

Object.assign(, key: 2, key: undefined)

我想收到key: 2。目前我收到key: undefined

不是深度合并。

有可能吗?如果是,那么如何实现呢?

【问题讨论】:

注意:这个问题不包括我未定义的情况:***.com/questions/13852852/… 你可以取第二个对象,剪除undefined的任何值,然后在Object.assign中使用它 @vlaz 是否有原生的 ES6 方法来从对象中删除 undefiend 值? 好吧,如果你只用一点 ES6 来使用 ES5,那么 arr.filter(x => typeof x !== "undefined" ) 为什么你的对象中有未定义的值?只是想知道。 【参考方案1】:

如果你只需要值而不需要对象,你也可以使用对象解构:

const input =  a: 0, b: "", c: false, d: null, e: undefined ;
const  a = 1, b = 2, c = 3, d = 4, e = 5, f = 6  = input;
console.log(a, b, c, d, e, f);
// => 0, "", false, null, 5, 6

这只会覆盖缺失或未定义的值。

我经常将它用于函数参数的默认值,如下所示:

function f(options = ) 
  const  foo = 42, bar  = options;
  console.log(foo, bar);


f();
// => 42, undefined

f()
// => 42, undefined

f( foo: 123 )
// => 123, undefined

f( bar: 567 )
// => 42, 567

f( foo: 123, bar: 567 )
// => 123, 567

【讨论】:

【参考方案2】:

使用 ES2019/ES10 的新对象方法 Object.fromEntries(),可以更新 Michał 的 answer:

const assign = (target, ...sources) =>
  Object.assign(target, ...sources.map(x =>
    Object.fromEntries(
      Object.entries(x)
        .filter(([key, value]) => value !== undefined)
    )
  ))

console.log(assign(, key: 2, key: undefined))

【讨论】:

【参考方案3】:

使用 lodash 省略 nil 值,然后通过 spread 将两个对象合二为一

 ...(omitBy(key: 2, isNil)), ...(omitBy(key: undefined, isNil))

在此处查看有关 lodash 的更多信息https://lodash.com/docs/4.17.15

【讨论】:

【参考方案4】:

您无法直接使用Object.assign 来实现这一点,因为每个下一个对象都会为上一个合并重写相同的键。唯一的方法是使用一些手工制作的函数来过滤传入的对象。

function filterObject(obj) 
    const ret = ;
    Object.keys(obj)
        .filter((key) => obj[key] !== undefined)
        .forEach((key) => ret[key] = obj[key]);
    return ret;

【讨论】:

你也可以将谓词作为参数传递,这样它就可以像Array.filter 我认为您在obj[key] 之后缺少一个结束) @TechnoTim thnx,已修复 如何在deepmerge 中拥有相同的逻辑?【参考方案5】:

编写一个小工具来删除未定义的值:

function removeUndefined(obj) 
  for (let k in obj) if (obj[k] === undefined) delete obj[k];
  return obj;

然后

Object.assign(, key: 2, removeUndefined(key: undefined))

这似乎比编写您自己的 assign 更可取,使用有线行为来删除未定义的值。

【讨论】:

这种方法会改变传入的对象,在某些情况下可能会出现问题【参考方案6】:

您可以简单地过滤掉带有undefined 值的键,然后再将它们传递给Object.assign()

const assign = (target, ...sources) =>
  Object.assign(target, ...sources.map(x =>
    Object.entries(x)
      .filter(([key, value]) => value !== undefined)
      .reduce((obj, [key, value]) => (obj[key] = value, obj), )
  ))

console.log(assign(, key: 2, key: undefined))

【讨论】:

以上是关于(_.merge in ES6/ES7)Object.assign 不覆盖未定义的值的主要内容,如果未能解决你的问题,请参考以下文章

ES6/ES7 中“可选”对象键的简洁/简洁语法?

ES6/ES7 中“可选”对象键的简洁/简洁语法?

如何使用 ES6/ES7 语法导入 jQuery UI?

node mysql es6/es7改造

ES6/ES7/ES8常用特性和新特性

ES6/ES7/ES8常用特性和新特性