ES6解构
分解语法允许使用函数参数或变量来分解和重组对象。
限制是键的列表是预定义的,正如问题所提到的,它们不能以字符串形式列出。如果键是非字母数字(例如),则解构将变得更加复杂foo_bar
。
缺点是,这需要重复键列表,如果列表很长,则会导致冗长的代码。由于在这种情况下解构重复对象的文字语法,因此可以照原样复制和粘贴列表。
好处是它是ES6固有的高性能解决方案。
国际教育展
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
临时变量
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
字符串列表
根据问题的要求,选择的键的任意列表由字符串组成。这样就可以不预定义它们,而使用包含键名的变量,例如pick(obj, 'foo', someKey, ...moreKeys)
。
每个JS版本的单线都变得更短。
ES5
var subset = Object.keys(obj)
.filter(function (key) {
return ['foo', 'bar'].indexOf(key) >= 0;
})
.reduce(function (obj2, key) {
obj2[key] = obj[key];
return obj2;
}, {});
ES6
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => Object.assign(obj2, { [key]: obj[key] }), {});
或使用逗号运算符:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
ECMAScript 2017具有Object.entries
和Array.prototype.includes
,ECMAScript 2019具有Object.fromEntries
,可以在需要时进行填充,使任务更轻松:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
可以将单行代码重写为类似于Lodash的pick
辅助函数,或者omit
将键列表通过参数传递:
let pick = (obj, ...keys) => Object.fromEntries(
Object.entries(obj)
.filter(([key]) => keys.includes(key))
);
let subset = pick({ foo: 1, qux: 2 }, 'foo', 'bar'); // { foo: 1 }
关于遗失钥匙的注意事项
解构和传统的类似于Lodash的pick
函数之间的主要区别在于,解构包括undefined
子集中不存在带有值的选取键:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
此行为可能是或不希望的。不能为解构语法而更改它。
pick
可以通过迭代选择的键列表来将While 更改为包括丢失的键:
let inclusivePick = (obj, ...keys) => Object.fromEntries(
keys.map(key => [key, obj[key]])
);
let subset = inclusivePick({ foo: 1, qux: 2 }, 'foo', 'bar'); // { foo: 1, bar: undefined }