618 Stimmen

Wie klont man ein Array von Objekten in JavaScript?

...wo jedes Objekt auch Verweise auf andere Objekte innerhalb desselben Arrays hat?

Als ich zum ersten Mal mit diesem Problem konfrontiert wurde, dachte ich nur an etwas wie

var clonedNodesArray = nodesArray.clone()

existieren würde, und suchte nach Informationen darüber, wie man Objekte in JavaScript klont. Ich habe gefunden eine Frage auf Stack Overflow (beantwortet von demselben @JohnResig) und er wies darauf hin, dass man mit jQuery Folgendes tun kann

var clonedNodesArray = jQuery.extend({}, nodesArray);

um ein Objekt zu klonen. Ich habe dies jedoch ausprobiert, und es werden nur die Referenzen der Objekte im Array kopiert. Wenn ich also

nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"

wird der Wert sowohl von nodesArray[0] als auch von clonedNodesArray[0] "grün" sein. Dann habe ich versucht

var clonedNodesArray = jQuery.extend(true, {}, nodesArray);

das ein Objekt tief kopiert, aber ich bekomme " zu viel Rekursion " und " Kontrollstapelüberlauf " Nachrichten von beiden Firebug y Oper Libelle beziehungsweise.

Wie würden Sie das machen? Ist das etwas, das gar nicht gemacht werden sollte? Gibt es eine wiederverwendbare Möglichkeit, dies in JavaScript zu tun?

9voto

George Punkte 99

Möglicherweise gibt es eine einfache Möglichkeit, dies zu tun, ohne dass man eine mühsame Rekursion durchführen muss und nicht alle Feinheiten des betreffenden Objekts kennt. Mit jQuery, konvertieren Sie einfach Ihr Objekt in JSON mit dem jQuery $.toJSON(myObjectArray) nehmen Sie dann Ihre JSON-Zeichenfolge und werten sie in ein Objekt zurück. BÄM! Fertig, und fertig! Problem gelöst. :)

var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));

9voto

Rafael Grilli Punkte 1557

Diese Methode ist sehr einfach und Sie können Ihren Klon ändern, ohne das ursprüngliche Array zu verändern.

// Original Array
let array = [{name: 'Rafael'}, {name: 'Matheus'}];

// Cloning Array
let clone = array.map(a => {return {...a}})

// Editing the cloned array
clone[1].name = 'Carlos';

console.log('array', array)
// [{name: 'Rafael'}, {name: 'Matheus'}]

console.log('clone', clone)
// [{name: 'Rafael'}, {name: 'Carlos'}]

9voto

bozdoz Punkte 11750

Ich beantworte diese Frage, weil es keine einfache und eindeutige Lösung für das Problem des "Klonens eines Arrays von Objekten in JavaScript" zu geben scheint:

function deepCopy (arr) {
    var out = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        var item = arr[i];
        var obj = {};
        for (var k in item) {
            obj[k] = item[k];
        }
        out.push(obj);
    }
    return out;
}

// test case

var original = [
    {'a' : 1},
    {'b' : 2}
    ];

var copy = deepCopy(original);

// change value in copy
copy[0]['a'] = 'not 1';

// original[0]['a'] still equals 1

Diese Lösung iteriert die Array-Werte, iteriert die Objektschlüssel, speichert letztere in einem neuen Objekt und verschiebt dieses neue Objekt in ein neues Array.

Ver jsfiddle . Anmerkung: eine einfache .slice() o [].concat() ist nicht genug für die Objekte innerhalb das Array.

5voto

Georg Schölly Punkte 120083

Wie Daniel Lew erwähnte, haben zyklische Graphen einige Probleme. Wenn ich dieses Problem hätte, würde ich entweder spezielle clone() Methoden zu den problematischen Objekten oder merken, welche Objekte ich bereits kopiert habe.

Ich würde es mit einer Variablen machen copyCount die sich jedes Mal um 1 erhöht, wenn Sie Ihren Code hineinkopieren. Ein Objekt, das einen niedrigeren copyCount als der aktuelle Kopiervorgang kopiert wird. Wenn nicht, sollte auf die bereits vorhandene Kopie verwiesen werden. Dies macht es notwendig, vom Original auf seine Kopie zu verweisen.

Es gibt noch ein Problem: Speicher. Wenn Sie diesen Verweis von einem Objekt zum anderen haben, ist es wahrscheinlich, dass der Browser diese Objekte nicht freigeben kann, da sie immer von irgendwoher referenziert werden. Sie müssten einen zweiten Durchlauf machen, bei dem Sie alle Kopierreferenzen auf Null setzen. (Wenn Sie dies tun, müssen Sie keine copyCount sondern ein boolescher isCopied würde ausreichen, da Sie den Wert im zweiten Durchgang zurücksetzen können).

5voto

Chtiwi Malek Punkte 10464

Ich verwende das neue ECMAScript 6 Objekt.zuweisen Methode:

let oldObject = [1, 3, 5, "test"];
let newObject = Object.assign({}, oldObject);

Das erste Argument dieser Methode ist das zu aktualisierende Array. Wir übergeben ein leeres Objekt, weil wir ein neues Objekt haben wollen.

Wir können auch diese Syntax verwenden, die die gleiche ist, aber kürzer:

let newObject = [...oldObject];

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X