Déstructuration ES6
La syntaxe de déstructuration permet de déstructurer et de recombiner un objet, avec des paramètres de fonction ou des variables.
La limitation est qu'une liste de clés est prédéfinie, elles ne peuvent pas être répertoriées comme des chaînes, comme le mentionne la question. La déstructuration devient plus compliquée si une clé n'est pas alphanumérique, par exemple foo_bar.
L'inconvénient est que cela nécessite de dupliquer une liste de clés, ce qui entraîne un code détaillé au cas où une liste est longue. Étant donné que la déstructuration duplique la syntaxe littérale des objets dans ce cas, une liste peut être copiée et collée telle quelle.
L'avantage est que c'est une solution performante qui est naturelle pour ES6.
IIFE
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
Variables temporaires
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
Une liste de chaînes
La liste arbitraire des clés sélectionnées se compose de chaînes, comme l'exige la question. Cela permet de ne pas les prédéfinir et d'utiliser des variables qui contiennent des noms de clés, comme pick(obj, 'foo', someKey, ...moreKeys).
Une doublure devient plus courte avec chaque édition 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] }), {});
Ou avec un opérateur virgule:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
ECMAScript 2017 a Object.entrieset Array.prototype.includes, ECMAScript 2019 a Object.fromEntries, ils peuvent être polyfilled en cas de besoin et rendre la tâche plus facile:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
Un one-liner peut être réécrit comme une fonction d'assistance similaire à Lodashpick ou omitoù la liste des clés est passée par des 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 }
Une note sur les clés manquantes
La principale différence entre la déstructuration et la fonction conventionnelle de type Lodash pickest que la déstructuration inclut des clés choisies inexistantes avec une undefinedvaleur dans un sous-ensemble:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
Ce comportement peut être souhaitable ou non. Il ne peut pas être modifié pour la syntaxe de déstructuration.
Alors que pickpeut être modifié pour inclure les clés manquantes en itérant une liste de clés sélectionnées à la place:
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 }