wake-up-neo.net

Einzeiler, um einige Eigenschaften von Objekten in ES 6 zu übernehmen

Wie kann man eine Funktion schreiben, die in ES6 auf kompakteste Weise nur wenige Attribute benötigt?

Ich habe eine Lösung mit Destructuring + vereinfachtem Objektliteral gefunden, aber ich mag es nicht, dass die Liste der Felder im Code wiederholt wird.

Gibt es eine noch schlankere Lösung?

(v) => {
    let { id, title } = v;
    return { id, title };
}
131
kirilloid

Hier ist etwas Schlankeres, obwohl die Liste der Felder nicht wiederholt werden muss. Es verwendet "Parameter-Destrukturierung", um die Notwendigkeit des Parameters v zu vermeiden.

({id, title}) => ({id, title})

Die Lösung von @ethanBrown ist allgemeiner. Hier ist eine idiomatischere Version davon, die Object.assign und berechnete Eigenschaften (der [p]-Teil) verwendet:

function pick(o, ...props) {
    return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}

Wenn wir die Attribute der Eigenschaften, wie configurable und Getter und Setter, beibehalten möchten, und dabei auch nicht aufzuzählende Eigenschaften weglassen möchten,

function pick(o, ...props) {
    var has = p => o.propertyIsEnumerable(p),
        get = p => Object.getOwnPropertyDescriptor(o, p);

    return Object.defineProperties({},
        Object.assign({}, ...props
            .filter(prop => has(prop))
            .map(prop => ({prop: get(props)})))
    );
}
98
user663031

Ich glaube nicht, dass es eine Möglichkeit gibt, sie viel kompakter zu gestalten als Ihre Antwort (oder Torazburos), aber im Wesentlichen möchten Sie mit Underscores pick operation emulieren. Es wäre leicht genug, das in ES6 neu zu implementieren:

function pick(o, ...fields) {
    return fields.reduce((a, x) => {
        if(o.hasOwnProperty(x)) a[x] = o[x];
        return a;
    }, {});
}

Dann haben Sie eine praktische wiederverwendbare Funktion:

var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
39
Ethan Brown

Der Trick, um dies als Einzeiler zu lösen, besteht darin, den gewählten Ansatz umzudrehen: Anstatt mit dem ursprünglichen Objekt orig zu beginnen, kann man von den Schlüsseln ausgehen, die sie extrahieren möchten.

Mit Array#reduce kann man dann jeden benötigten Schlüssel auf dem leeren Objekt speichern, das als initialValue für die Funktion übergeben wird.

So wie:

const orig = {
  id: 123456789,
  name: 'test',
  description: '…',
  url: 'https://…',
};

const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});

console.log(filtered); // Object {id: 123456789, name: "test"}

17
Bramus

Eine kleine, etwas kürzere Lösung mit dem Komma-Operator:

const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
8
shesek

TC39s Objektrest/Spread-Eigenschaftsvorschlag macht dies ziemlich glatt:

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }

(Es hat den Nachteil, dass Sie die Variablen x und y erstellen, die Sie möglicherweise nicht benötigen.)

6
alxndr

Derzeit gibt es einen Strawman-Vorschlag zur Verbesserung der JavaScript-Syntax für Objektkurzzeichen, mit dem benannte Eigenschaften ohne Wiederholung ausgewählt werden können:

const source = {id: "68646", genre: "crime", title: "Scarface"};
const target = {};
Object.assign(target, {source.title, source.id});

console.log(picked);
// {id: "68646", title: "Scarface"}

Leider scheint der Vorschlag in absehbarer Zeit keine Wirkung zu entfalten. Zuletzt bearbeitet im Juli 2017 und immer noch ein Entwurf bei Stufe , was darauf hindeutet, dass der Autor es vielleicht vergessen oder vergessen hat.

ES5 und früher (nicht strikter Modus)

Die knappste mögliche Abkürzung, die ich mir vorstellen kann, beinhaltet ein altes Sprachmerkmal das niemand mehr benutzt:

Object.assign(target, {...(o => {
    with(o) return { id, title };
})(source)});

with -Anweisungen sind im strikten Modus verboten, sodass dieser Ansatz für 99,999% des modernen JavaScript unbrauchbar ist. Etwas schade, denn dies ist die einzige halbwegs anständige Verwendung, die ich für die Funktion with gefunden habe. ????

1
user458541

ES6 war die neueste Spezifikation zu dem Zeitpunkt, als die Frage geschrieben wurde. Wie in diese Antwort erläutert, ist die Schlüsselauswahl in ES2019 erheblich kürzer als in ES6:

Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => ['foo', 'bar'].includes(key))
)
1
Estus Flask

Eine Möglichkeit könnte darin bestehen, destructuring zu verwenden, um einem leeren Objekt Eigenschaften zuzuweisen.

let person = {
    fname:'tom',
    lname:'jerry',
    aage:100
}

let newPerson = {};

({fname: newPerson.fname, lname: newPerson.lname} = person);

console.log(newPerson);
1
Saksham

Ich habe eine ähnliche Lösung wie die Lösung von Ethan Brown, aber noch kürzer - pick-Funktion. Eine andere Funktion pick2 ist etwas länger (und langsamer), ermöglicht jedoch das Umbenennen von Eigenschaften auf ähnliche Weise wie bei ES6.

const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})

const pick2 = (o, ...props) => props.reduce((r, expr) => {
  const [p, np] = expr.split(":").map( e => e.trim() )
  return p in o ? {...r, [np || p]: o[p]} : r
}, {}) 

Hier ist das Anwendungsbeispiel:

const d = { a: "1", c: "2" }

console.log(pick(d, "a", "b", "c"))        // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }
1

Ich habe diese Lösung benötigt, wusste aber nicht, ob die vorgeschlagenen Schlüssel verfügbar sind. Also nahm ich die Antwort von @torazaburo und verbesserte mich für meinen Anwendungsfall:

function pick(o, ...props) {
  return Object.assign({}, ...props.map(prop => {
    if (o[prop]) return {[prop]: o[prop]};
  }));
}

// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }
0
Alwin Kesler

inspiriert durch den Reduktionsansatz von https://stackoverflow.com/users/865693/shesek :

const pick = (orig, ...keys) => keys.reduce((acc, key) => ({...acc, [key]: orig[key]}), {})

verwendungszweck:

pick({ model : 'F40', manufacturer: 'Ferrari', productionYear: 1987 }, 'model', 'productionYear') führt zu: {model: "F40", productionYear: 1987}

0
Kevin K.