ES6 destructuring
Destructuring syntax allows to destructure and recombine an object, with either function parameters or variables.
The limitation is that a list of keys is predefined, they cannot be listed as strings, as the question mentions. Destructuring becomes more complicated if a key is non-alphanumeric, e.g. foo_bar
.
The downside is that this requires to duplicate a list of keys, this results in verbose code in case a list is long. Since destructuring duplicates object literal syntax in this case, a list can be copied and pasted as is.
The upside is that it's performant solution that is natural to ES6.
IIFE
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
Temporary variables
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
A list of strings
Arbitrary list of picked keys consists of strings, as the question requires. This allows to not predefine them and use variables that contain key names, like pick(obj, 'foo', someKey, ...moreKeys)
.
A one-liner becomes shorter with each JS edition.
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] }), {});
Or with comma operator:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
ECMAScript 2017 has Object.entries
and Array.prototype.includes
, ECMAScript 2019 has Object.fromEntries
, they can be polyfilled when needed and make the task easier:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
A one-liner can be rewritten as helper function similar to Lodash pick
or omit
where the list of keys is passed through arguments:
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 }
A note about missing keys
The major difference between destructuring and conventional Lodash-like pick
function is that destructuring includes non-existent picked keys with undefined
value in a subset:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
This behaviour may or not be desirable. It cannot be changed for destructuring syntax.
While pick
can be changed to include missing keys by iterating a list of picked keys instead:
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 }
0
Created by Estus Flask on 2020-03-10 00:44:33 +0000 UTC
Share