ES6 destrutturante
La sintassi di distruzione consente di destrutturare e ricombinare un oggetto, con parametri di funzione o variabili.
Il limite è che un elenco di chiavi è predefinito, non possono essere elencate come stringhe, come menzionato nella domanda. La distruzione diventa più complicata se una chiave non è alfanumerica, ad es foo_bar.
Il rovescio della medaglia è che questo richiede di duplicare un elenco di chiavi, questo si traduce in un codice dettagliato nel caso in cui un elenco sia lungo. Poiché in questo caso la destrutturazione dei duplicati oggetto sintassi letterale, un elenco può essere copiato e incollato così com'è.
Il lato positivo è che è la soluzione performante naturale per ES6.
IIFE
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
Variabili temporanee
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
Un elenco di stringhe
L'elenco arbitrario delle chiavi selezionate è costituito da stringhe, come richiesto dalla domanda. Ciò consente di non predefinirli e utilizzare variabili che contengono nomi di chiavi, come pick(obj, 'foo', someKey, ...moreKeys).
Un one-liner diventa più corto con ogni edizione 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] }), {});
O con operatore virgola:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
ECMAScript 2017 ha Object.entriese Array.prototype.includes, ECMAScript 2019 ha Object.fromEntries, possono essere polifillati quando necessario e semplificare l'attività:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
Un one-liner può essere riscritto come funzione di supporto simile a Lodashpick o in omitcui l'elenco di chiavi viene passato attraverso argomenti:
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 }
Una nota sulle chiavi mancanti
La principale differenza tra la destrutturazione e la tradizionale pickfunzione simile a Lodash è che la destrutturazione include chiavi scelte inesistenti con undefinedvalore in un sottoinsieme:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
Questo comportamento può essere o meno desiderabile. Non può essere modificato per la sintassi destrutturante.
Mentre pickpuò essere modificato per includere le chiavi mancanti ripetendo invece un elenco di chiavi selezionate:
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 }