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

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

有这个sn-p:

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

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

不是深度合并。

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

【问题讨论】:

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

标签: javascript ecmascript-6 lodash babeljs ecmascript-2016


【解决方案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}))

        【讨论】:

          猜你喜欢
          • 2019-07-20
          • 2020-03-28
          • 2018-06-16
          • 2017-05-26
          • 1970-01-01
          • 2016-10-29
          • 2023-04-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多