(_.merge in ES6/ES7)Object.assign 不覆盖未定义的值
(_.merge in ES6/ES7)Object.assign without overriding undefined values
lodash 中有 _.merge 功能。我想在 ES6 或 ES7 中实现同样的事情。
有这个片段:
Object.assign({}, {key: 2}, {key: undefined})
我想收到{key: 2}
。目前我收到 {key: undefined}
这不是深度合并。
可能吗?如果是那么如何实现?
你无法通过直接使用 Object.assign
来实现这一点,因为每个下一个对象都会为上一个合并重写相同的键。唯一的方法是使用一些手工制作的函数来过滤传入的对象。
function filterObject(obj) {
const ret = {};
Object.keys(obj)
.filter((key) => obj[key] !== undefined)
.forEach((key) => ret[key] = obj[key]);
return ret;
}
您可以简单地过滤掉具有 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}))
编写一个小实用程序来删除未定义的值:
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
具有连线行为以删除未定义值更可取。
使用 lodash 省略 nil 值,然后通过 spread 将两个对象合二为一
{ ...(omitBy({key: 2}, isNil)), ...(omitBy({key: undefined}, isNil))}
在此处查看有关 lodash 的更多信息https://lodash.com/docs/4.17.15
使用ES2019/ES10的新对象方法,Object.fromEntries()
, Michał's 可以更新:
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}))
如果你只需要值而不需要对象,你也可以使用对象解构:
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
lodash 中有 _.merge 功能。我想在 ES6 或 ES7 中实现同样的事情。
有这个片段:
Object.assign({}, {key: 2}, {key: undefined})
我想收到{key: 2}
。目前我收到 {key: undefined}
这不是深度合并。
可能吗?如果是那么如何实现?
你无法通过直接使用 Object.assign
来实现这一点,因为每个下一个对象都会为上一个合并重写相同的键。唯一的方法是使用一些手工制作的函数来过滤传入的对象。
function filterObject(obj) {
const ret = {};
Object.keys(obj)
.filter((key) => obj[key] !== undefined)
.forEach((key) => ret[key] = obj[key]);
return ret;
}
您可以简单地过滤掉具有 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}))
编写一个小实用程序来删除未定义的值:
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
具有连线行为以删除未定义值更可取。
使用 lodash 省略 nil 值,然后通过 spread 将两个对象合二为一
{ ...(omitBy({key: 2}, isNil)), ...(omitBy({key: undefined}, isNil))}
在此处查看有关 lodash 的更多信息https://lodash.com/docs/4.17.15
使用ES2019/ES10的新对象方法,Object.fromEntries()
, Michał's
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}))
如果你只需要值而不需要对象,你也可以使用对象解构:
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