ES6-Destrukturierung
Die Destrukturierungssyntax ermöglicht das Destrukturieren und Rekombinieren eines Objekts mit Funktionsparametern oder Variablen.
Die Einschränkung besteht darin, dass eine Liste von Schlüsseln vordefiniert ist. Sie können nicht als Zeichenfolgen aufgeführt werden, wie in der Frage erwähnt. Die Destrukturierung wird komplizierter, wenn ein Schlüssel nicht alphanumerisch ist, z foo_bar.
Der Nachteil ist, dass dies das Duplizieren einer Liste von Schlüsseln erfordert. Dies führt zu ausführlichem Code, falls eine Liste lang ist. Da die Destrukturierung in diesem Fall die Objektliteral-Syntax dupliziert, kann eine Liste unverändert kopiert und eingefügt werden.
Der Vorteil ist, dass es sich um eine performante Lösung handelt, die für ES6 selbstverständlich ist.
IIFE
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
Temporäre Variablen
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
Eine Liste von Zeichenfolgen
Die beliebige Liste der ausgewählten Schlüssel besteht je nach Frage aus Zeichenfolgen. Dies ermöglicht es, sie nicht vordefinieren und Variablen zu verwenden, die Schlüsselnamen enthalten, wie z pick(obj, 'foo', someKey, ...moreKeys).
Ein Einzeiler wird mit jeder JS-Ausgabe kürzer.
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] }), {});
Oder mit Komma-Operator:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
ECMAScript 2017 hat Object.entriesund Array.prototype.includesECMAScript 2019 hat Object.fromEntries, sie können bei Bedarf polygefüllt werden und erleichtern die Aufgabe:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
Ein Einzeilerpick kann als Hilfsfunktion ähnlich wie Lodash umgeschrieben werden oder omitwenn die Liste der Schlüssel über Argumente übergeben wird:
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 }
Ein Hinweis zu fehlenden Schlüsseln
Der Hauptunterschied zwischen der Destrukturierung und der herkömmlichen Lodash-ähnlichen pickFunktion besteht darin, dass die Destrukturierung nicht vorhandene ausgewählte Schlüssel mit dem undefinedWert in einer Teilmenge enthält:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
Dieses Verhalten kann wünschenswert sein oder nicht. Es kann nicht für die Destrukturierungssyntax geändert werden.
Während pickkann geändert werden, um fehlende Schlüssel einzuschließen, indem stattdessen eine Liste der ausgewählten Schlüssel wiederholt wird:
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 }