2016-05-01 6 views
2

Ich bin auf der Suche nach einer Funktion identisch mit lodashs _.set, außer es sollte ein neues Objekt ohne Änderung des Originals zurückgeben. Gibt es irgendwelche Implementierungen davon?Suche nach Funktion identisch mit lodash's [_.set]()

Im Moment bin ich tief-Klonen und dann setzen:

let data = _.cloneDeep(this.state.data); 
_.set(data, name, value); 
this.setState({data}) 

Aber ich glaube nicht, es ist notwendig, um eine vollständige tiefe Klon zu tun, würden wir nur einen flachen Klon des tun müssen Objekt auf der tiefsten Ebene, nein?

z.B.

let oldData = { 'a': [{ 'b': { 'c': 3 }, 'd': {'e': 4} }] }; 
let newDate = withValue(oldData, 'a[0].b.c', 5); 

Die vorgeschlagene withValue Funktion würde einen flachen Klon von a, a[0] und a[0].b ausführen und ändern Sie dann die neue a[0].b.c bis 5. Wir würden keine Kopie a[0].d vornehmen müssen.

+0

Nein, das ist nicht ausreichend. Dies würde nicht garantieren, dass eine Mutation des anderen Objekts die neue nicht ändert. Sie müssen also entweder das reine JS-Objekt tiefklonen oder etwas verwenden, das Datenstrukturen für Sie umschließt (wie zB immutablejs). – zerkms

+0

Ab der Reaktion - "Unsetting" wird nicht helfen, da reagiert das übergebene Objekt mit dem bestehenden. – zerkms

+0

@zerkms Was passiert, wenn ich weiß, dass der alte ('this.state.data') niemals mutiert wird, also muss ich mich nicht darum sorgen, dass er den neuen verändert? – mpen

Antwort

3

Dies wird eine mehrteilige Antwort sein.

Immutable Satz:

Wie Sie verwenden lodash, können Sie die FP version of lodash verwenden und .set (oder .setWith in der Lage sein, ein Objekt Pfad zu liefern), die eine unveränderliche Update tun.

Oder, wie dies aussieht wie eine React Codebase können Sie die $set helper of React verwenden.

Oder Sie können einfach verwenden, um die Spread Operator:

const newObj = {...oldObj, prop: newValue } 

Oder Object.assign:

const newObj = Object.assign({}, oldObj, { prop: newValue }); 

Performance:

Wie Sie die Leistung zu erwähnen (und nicht nur tief Klonen eines Objekts) möchten Sie vielleicht in ein unveränderliches Framework schauen. Die besser entwickelten Codebasen erhöhen die Leistung durch verschiedene Maßnahmen. Z.B. hier ist was immutable.js sagt:

Diese Datenstrukturen auf modernen JavaScript VMs hocheffiziente sind durch strukturelle Sharing über Hash-Karten versucht und Vektor verwendet versucht

... und Mori sagt:

Effiziente, unveränderliche Datenstrukturen - kein Klonen erforderlich [...] Moderne JavaScript-Engines wie V8, JavaScriptCore und SpiderMonkey liefern die Leistung, die benötigt wird, um persistente Datenstrukturen gut zu implementieren.

+0

'$ set', spread und' Object.assign' unterstützen keine punktierte Notation. FP-Version könnte funktionieren. Will React eine 'Immutable.Map' auf' this.setState' übernehmen? Das ist, was Sie vorschlagen, dass ich richtig verwende? – mpen

+0

Persönlich empfehle ich dringend Immutable.js. Sehen Sie sich die Methode 'setIn' an, um ein Objekt tief zu setzen. Sie können den Status sehr einfach auf eine Immutable.Map setzen. Ich würde sagen, das ist die häufigste Verwendung von Immutable;) –

2

lodash/fp als Emil suggested sollte funktionieren.

Beispiel:

const setIn = require('lodash/fp/set'); 
this.setState({data: setIn(name, value, this.state.data)}); 

N. B.Die Reihenfolge der Argumente unterscheidet sich von der regulären lodash.