2014-11-16 1 views
5

Wie kann man ein ganzes Objekt aktualisieren, sagen:ohne Bezug zu ersetzen

var x = {a:1} 
function modify(obj) { 
    obj = {b:2} 
} 
modify(x) 
console.log(x) // {a:1} 

Aber die Referenz halten? Ich möchte, dass das Objekt außerhalb der Funktion geändert wird.

Mein speziellen Fall verwendet lodash.pick in meiner Funktion:

if (whitelist) { 
    obj = _.pick(obj, whitelist) 
} 

Ich kann keine pick Funktion zu finden scheinen, dass das Objekt modifiziert. Gibt es eine Möglichkeit, dies zu tun, oder muss ich Kopien des Objekts zurückgeben?

Antwort

8

delete alles aus dem alten Objekt, und dann neue Eigenschaften hinzufügen, Tasten- by-Taste:

function modify(obj, newObj) { 
 

 
    Object.keys(obj).forEach(function(key) { 
 
    delete obj[key]; 
 
    }); 
 

 
    Object.keys(newObj).forEach(function(key) { 
 
    obj[key] = newObj[key]; 
 
    }); 
 
    
 
} 
 

 
var x = {a:1} 
 
modify(x, {b:42}) 
 
document.write(JSON.stringify(x));

Wenn Sie sich fragen, ob es eine gute Idee, in gen ist es ist die Antwort, nein. Konstruieren Sie ein neues Objekt, geben Sie es aus der Funktion zurück und weisen Sie es zu - dies ist ein sehr bevorzugter Weg.

+0

Schöne Art, dies zu tun. Und ich stimme deinem Abschlusspunkt zu. – Aravind

+0

Am Ende habe ich lodash '_.cloneDeep' verwendet und ein neues Objekt zurückgegeben, aber das wäre die beste Lösung für die Frage. Und einverstanden, das ist eine schreckliche Praxis. – Garrett

+0

Kann jemand erklären, warum das so schrecklich ist? Mein Szenario besteht darin, dass ich ein großes Array von Objekten habe und ein unterstützendes "Referenzobjekt" verwende, um auf diese mit ihren IDs zuzugreifen, anstatt das Array durchlaufen zu müssen. Ie 'modify (referenceObject [objectId], updateObject);' –

-2

Warum bearbeitet ändern nicht das Objekt, auf das sich obj bezieht?

Da innerhalb ändern, wenn Sie schreiben:

obj = {b:2} 

Beachten Sie, dass obj eine lokale Variable ist zu den Funktionsaufruf von ändern. Ein neues Objekt {b:2} wird erstellt, und die lokale Variable obj verweist nun auf dieses neue Objekt. Erinnern Sie sich, dass die Variable x immer noch auf das Objekt {a:1} verweist.

Wenn x ist eine globale Variable und wenn es keine lokale Variable innerhalb der Funktion mit dem Namen ist, dann können Sie tun:

var x = {a:1}; 
function modify() { 
    x = {b:2} 
} 
modify(); 
console.log(x) // {b:2} 

Warum funktioniert der obige Code funktioniert?

Wenn Sie rufen ändern(), versucht es, zu sehen, ob es eine lokale Variable x hat, da sie nicht finden können, sieht es in der Anwendungsbereich Kette. Der nächste Bereich, um nach diesem Funktionsaufruf zu suchen, ist der globale Gültigkeitsbereich, und tatsächlich haben wir dort eine x Variable. Daher wird die globale Variable x jetzt gesetzt.

+0

Idealer ändert die Funktion den übergebenen in Variable. Es sieht so aus, als müsste ich das Objekt zurückgeben, anstatt es nur zu modifizieren. – Garrett

+0

Aber wenn Sie "obj.a = 3" anstelle von "obj = {b: 2}" in der Funktion modify verwenden, wird der x-Wert geändert. Wie erklären Sie das? –

+0

@plbsam: Das liegt daran, wenn Sie obj.a = 3 schreiben, sucht Javascript zuerst nach der Eigenschaft a in obj. Wenn Sie die Funktion modify (x) aufgerufen haben, wird die lokale Variable obj der Funktion modify auf x gesetzt, sodass obj auf das gleiche Objekt zeigt, auf das x zeigt. Also wenn du obj.a = 3 schreibst; , setzt es die Eigenschaft desselben Objekts, auf das x zeigt. Sinn ergeben? – Aravind

1

Sie können dies erreichen (nicht genau das, was Sie wollen), wenn Sie Ihr Objekt wickeln und die Funktion wie folgt ändern ändern,

var wrapper = {}; 
wrapper.x = {a:1}; 
function modify(obj, key) { 
    obj[key] = {b:2}; 
} 
modify(wrapper, 'x'); 
console.log(wrapper.x); // {b:2} 
0

Ich hatte dieses Problem. Nach einigen Nachforschungen entschied ich, objectTwo in eine JSON-Zeichenfolge zu konvertieren und dann objectOne durch die geparste Version zu ersetzen.Mit anderen Worten:

var mObjectOne = { ExampleProperty: 10 }; 
var mObjectTwo = { ExampleProperty: 15 }; 

// I wanted mObjectOne to hold the same data as mObjectTwo, but keep a separate reference 
var mObjectTwoAsJSON = JSON.stringify(mObjectTwo); 
mObjectOne = JSON.parse(mObjectTwoAsJSON); 

// Now the references are still different, as desired, but the object data has been updated. 

Danke,