Restrukturyzacja ES6
Składnia destrukcyjna pozwala na destrukcję i rekombinację obiektu, z parametrami funkcji lub zmiennymi.
Ograniczeniem jest to, że lista kluczy jest predefiniowana, nie można ich wymienić jako ciągów, jak wspomniano w pytaniu. Restrukturyzacja staje się bardziej skomplikowana, jeśli klucz nie jest alfanumeryczny, np foo_bar.
Minusem jest to, że wymaga to powielenia listy kluczy, skutkuje to pełnym kodem na wypadek, gdyby lista była długa. Ponieważ w tym przypadku destrukcja duplikuje składnię dosłowną obiektu, listę można skopiować i wkleić bez zmian.
Plusem jest to, że jest to wydajne rozwiązanie, które jest naturalne dla ES6.
IIFE
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
Zmienne tymczasowe
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
Lista ciągów
Dowolna lista wybranych kluczy składa się z ciągów znaków, zgodnie z wymaganiami pytania. Pozwala to nie predefiniować ich i używać zmiennych zawierających nazwy kluczy, takich jak pick(obj, 'foo', someKey, ...moreKeys).
Jedna linijka staje się krótsza z każdą edycją 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] }), {});
Lub z przecinkiem:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
ECMAScript 2017 ma, Object.entriesa Array.prototype.includesECMAScript 2019 ma Object.fromEntries, mogą być wypełniane w razie potrzeby i ułatwiają zadanie:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
Jednowierszowypick może być przepisany jako funkcja pomocnicza podobna do Lodash lub omitgdy lista kluczy jest przekazywana przez argumenty:
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 }
Uwaga na temat brakujących kluczy
Główną różnicą między destrukcją a tradycyjną funkcją typu Lodash pickjest to, że destrukcja obejmuje nieistniejące wybrane klucze o undefinedwartości w podzbiorze:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
To zachowanie może być pożądane lub nie. Nie można go zmienić dla składni destrukcyjnej.
Chociaż pickmożna zmienić, aby uwzględnić brakujące klucze, iterując zamiast tego listę wybranych kluczy:
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 }