Beim Kopieren eines Arrays in JavaScript in ein anderes Array:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
Mir wurde klar, dass arr2
sich dies auf dasselbe Array bezieht arr1
und nicht auf ein neues, unabhängiges Array. Wie kann ich das Array kopieren, um zwei unabhängige Arrays zu erhalten?
javascript
arrays
Dan
quelle
quelle
slice
undsplice
Operationen sowie einen neuen Spread-Operator undArray.from
eine viel langsamere Implementierung. Schauen Sie sich perfjs.fnfovar arr2 = arr1.splice();
um tiefe Kopie, aber diese Technik wird nicht funktionieren , wenn die Elemente im Array enthalten wörtliche Strukturen (zB[]
oder{}
) oder Prototyp - Objekte (dhfunction () {}
,new
usw.). Weitere Lösungen finden Sie in meiner Antwort unten.let arr2 = [...arr1];
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Antworten:
Benutze das:
Grundsätzlich klont die
slice()
Operation das Array und gibt einen Verweis auf ein neues Array zurück.Beachten Sie auch Folgendes:
Kopiert für Referenzen, Zeichenfolgen und Zahlen (und nicht das eigentliche Objekt)
slice()
Objektreferenzen in das neue Array. Sowohl das ursprüngliche als auch das neue Array beziehen sich auf dasselbe Objekt. Wenn sich ein referenziertes Objekt ändert, sind die Änderungen sowohl für das neue als auch für das ursprüngliche Array sichtbar.Grundelemente wie Zeichenfolgen und Zahlen sind unveränderlich, sodass Änderungen an Zeichenfolgen oder Zahlen nicht möglich sind.
quelle
.slice()
mit.splice()
, was Ihnen ein leeres Array gibt. Großer Unterschied.In Javascript hängen Deep-Copy-Techniken von den Elementen in einem Array ab. Fangen wir dort an.
Drei Arten von Elementen
Elemente können sein: Literalwerte, Literalstrukturen oder Prototypen.
Aus diesen Elementen können drei Arten von Arrays erstellt werden.
Deep Copy-Techniken hängen von den drei Array-Typen ab
Basierend auf den Elementtypen im Array können wir verschiedene Techniken zum Deep Copy verwenden.
Array von literal-Werten (Typ 1)
Die
[...myArray]
,myArray.splice(0)
,myArray.slice()
undmyArray.concat()
Techniken können auf tiefe Kopie Arrays mit literalen Werten verwendet werden (boolean, Anzahl und string) nur; Hier hat der Spread-Operator[...myArray]
die beste Leistung ( https://measurethat.net/Benchmarks/Show/4281/0/spread-array-performance-vs-slice-splice-concat ).Array von Literalwerten (Typ1) und Literalstrukturen (Typ2)
Mit dieser
JSON.parse(JSON.stringify(myArray))
Technik können Literalwerte (Boolescher Wert, Zahl, Zeichenfolge) und Literalstrukturen (Array, Objekt), jedoch keine Prototypobjekte, tief kopiert werden.Alle Arrays (Typ1, Typ2, Typ3)
Mit der jQuery-
$.extend(myArray)
Technik können alle Array-Typen tief kopiert werden. Bibliotheken wie Underscore und Lo-Dash bieten ähnliche Deep-Copy-Funktionen wie jQuery$.extend()
, weisen jedoch eine geringere Leistung auf. Überraschender ist,$.extend()
hat eine höhere Leistung als dieJSON.parse(JSON.stringify(myArray))
Technik http://jsperf.com/js-deep-copy/15 .Und für Entwickler, die Bibliotheken von Drittanbietern (wie jQuery) scheuen, können Sie die folgende benutzerdefinierte Funktion verwenden. Das hat eine höhere Leistung als $ .extend und kopiert alle Arrays tief.
Also um die Frage zu beantworten ...
Frage
Antworten
Da
arr1
es sich um ein Array von Literalwerten (Boolescher Wert, Zahl oder Zeichenfolge) handelt, können Sie jede oben beschriebene Deep-Copy-Technik verwenden, bei der der Spread-Operator...
die höchste Leistung aufweist.quelle
arr1
. Es ist sehr selten, dass dies der Fall sein wird. Verwenden Siesplice
Obliteratesarr1
, das ist also überhaupt keine Kopie. Die VerwendungJSON
schlägt fehl, wenn einer der Werte im Array Funktionen ist oder Prototypen enthält (z. B. aDate
).[0,"1",{2:3},function random() {return 4;}, [[5,6,7],[8,9,10],[11,12,13]]]
und jedem anderen Array.Sie können Array-Spreads verwenden,
...
um Arrays zu kopieren.const itemsCopy = [...items];
Auch wenn Sie ein neues Array erstellen möchten, wobei das vorhandene Teil davon ist:
Array-Spreads werden jetzt in allen gängigen Browsern unterstützt. Wenn Sie jedoch ältere Unterstützung benötigen, verwenden Sie Typoskript oder Babel und kompilieren Sie zu ES5.
Weitere Infos zu Spreads
quelle
Keine jQuery erforderlich ... Arbeitsbeispiel
Dadurch wird das Array von der Startposition kopiert
0
bis zum Ende des Arrays kopiert.Es ist wichtig zu beachten, dass es für primitive Typen (Zeichenfolge, Nummer usw.) wie erwartet funktioniert, und auch das erwartete Verhalten für Referenztypen zu erklären ...
Wenn Sie ein Array von Referenztypen haben, sagen Sie Typ
Object
. Das Array wird kopiert, aber beide Arrays enthalten Verweise auf dasselbeObject
. In diesem Fall scheint das Array als Referenz kopiert zu sein, obwohl das Array tatsächlich kopiert wird.quelle
var arr2 = JSON.stringify(arr1); arr2 = JSON.parse(arr2);
Eine Alternative zu
slice
istconcat
, die auf zwei Arten verwendet werden kann. Die erste davon ist vielleicht besser lesbar, da das beabsichtigte Verhalten sehr klar ist:Die zweite Methode ist:
Cohen (in den Kommentaren) wies darauf hin, dass diese letztere Methode eine bessere Leistung hat .
Die Art und Weise, wie dies funktioniert, ist, dass die
concat
Methode ein neues Array erstellt, das aus den Elementen in dem Objekt besteht, für das es aufgerufen wird, gefolgt von den Elementen aller Arrays, die als Argumente an sie übergeben werden. Wenn also keine Argumente übergeben werden, wird das Array einfach kopiert.Lee Penkman weist auch in den Kommentaren darauf hin, dass Sie ein leeres Array wie folgt zurückgeben können , wenn eine Chance
array1
bestehtundefined
:Oder für die zweite Methode:
Beachten Sie, dass Sie dies auch tun können mit
slice
:var array2 = (array1 || []).slice();
.quelle
[].concat(array1)
zurückgegeben wird,[array1]
z. B. wenn es undefiniert ist, erhalten Sie[undefined]
. Ich mache manchmalvar array2 = [].concat(array1 || []);
So habe ich es gemacht, nachdem ich viele Ansätze ausprobiert habe:
Dadurch wird eine neue tiefe Kopie erstellt, die nicht mit der ersten verwandt ist (keine flache Kopie).
Auch dies wird natürlich keine Ereignisse und Funktionen klonen, aber das Gute ist, dass Sie es in einer Zeile tun können, und es kann für jede Art von Objekt (Arrays, Strings, Zahlen, Objekte ...) verwendet werden.
quelle
Date
oder in der Tat an allem, was einen Prototyp hat. Außerdem werdenundefined
s innull
s konvertiert .Einige der genannten Methoden funktionieren gut, wenn Sie mit einfachen Datentypen wie Zahl oder Zeichenfolge arbeiten. Wenn das Array jedoch andere Objekte enthält, schlagen diese Methoden fehl. Wenn wir versuchen, ein Objekt von einem Array an ein anderes zu übergeben, wird es als Referenz übergeben, nicht als Objekt.
Fügen Sie Ihrer JavaScript-Datei den folgenden Code hinzu:
Und einfach benutzen
Es wird klappen.
quelle
.slice()
funktioniert immer noch gut, auch wenn Sie Objekte in Ihrem Array haben: jsfiddle.net/edelman/k525gAb ES2015,
quelle
Ich persönlich halte Array.from für eine besser lesbare Lösung. Achten Sie übrigens nur auf die Browserunterstützung.
quelle
.slice()
Lösung ist völlig unintuitiv. Danke dafür.Wichtig!
Die meisten Antworten hier funktionieren für bestimmte Fälle .
Wenn Sie sich nicht für tiefe / verschachtelte Objekte und Requisiten interessieren, verwenden Sie ( ES6 ):
let clonedArray = [...array]
Wenn Sie jedoch einen tiefen Klon ausführen möchten, verwenden Sie stattdessen Folgendes:
let cloneArray = JSON.parse(JSON.stringify(array))
Für lodash Benutzer:
let clonedArray = _.clone(array)
Dokumentationund
let clonedArray = _.cloneDeep(array)
Dokumentationquelle
Wenn Sie sich in einer Umgebung von ECMAScript 6 befinden und den Spread-Operator verwenden, können Sie dies folgendermaßen tun:
quelle
Hinzufügen zur Lösung von array.slice (); Beachten Sie, dass bei mehrdimensionalen Arrays Sub-Arrays durch Referenzen kopiert werden. Was Sie tun können, ist, jedes Sub-Array einzeln zu schleifen und zu schneiden ()
Das Gleiche gilt für ein Array von Objekten. Sie werden als Referenz kopiert. Sie müssen sie manuell kopieren
quelle
Primitive Werte werden immer an ihrem Wert übergeben (kopiert). Zusammengesetzte Werte werden jedoch als Referenz übergeben.
Wie kopieren wir diesen Arr?
Kopieren Sie ein Array in ES6
Kopieren Sie n Array in ES5
Warum wird "let arrCopy = arr" nicht als Wert übergeben?
Das Übergeben einer Variablen an eine andere bei zusammengesetzten Werten wie Object / Array verhält sich anders. Mit dem Operator asign für Copand-Werte übergeben wir einen Verweis auf ein Objekt. Aus diesem Grund ändert sich der Wert beider Arrays beim Entfernen / Hinzufügen von arr-Elementen.
Ausnahmen:
Wenn Sie der Variablen einen neuen Wert zuweisen, ändern Sie die Referenz selbst und dies wirkt sich nicht auf das ursprüngliche Objekt / Array aus.
Weiterlesen
quelle
Wie wir in Javascript Arrays und Objekte wissen auf Referenz, aber wie können wir das Array kopieren, ohne das ursprüngliche Array später zu ändern?
Hier sind einige Möglichkeiten, dies zu tun:
Stellen Sie sich vor, wir haben dieses Array in Ihrem Code:
1) Durchlaufen Sie das Array in einer Funktion und geben Sie ein neues Array wie folgt zurück:
2) Mit der Slice-Methode wird Slice zum Schneiden eines Teils des Arrays verwendet. Es schneidet einen Teil Ihres Arrays, ohne das Original zu berühren. Wenn Sie im Slice nicht den Anfang und das Ende des Arrays angeben, wird das Ganze geschnitten Array und erstellen Sie im Grunde eine vollständige Kopie des Arrays, so dass wir leicht sagen können:
3) Auch die Kontaktmethode dient zum Zusammenführen von zwei Arrays. Wir können jedoch nur eines der Arrays angeben und dann im Grunde genommen eine Kopie der Werte im neuen kontaktierten Array erstellen:
4) Auch die Stringify- und Parse-Methode wird nicht empfohlen, kann aber eine einfache Möglichkeit sein, Array und Objekte zu kopieren:
5) Die Methode Array.from wird nicht allgemein unterstützt. Überprüfen Sie vor der Verwendung die Unterstützung in verschiedenen Browsern:
6) ECMA6-Weg, auch nicht vollständig unterstützt, aber babelJs können Ihnen helfen, wenn Sie transpilieren möchten:
quelle
Jetzt können Sie eine der folgenden Aktionen ausführen, um eine Kopie eines Arrays zu erstellen.
ODER
ODER
ODER
ODER
Nun, wenn ich a ändere,
Dann ist a [1,2,3,5], aber b ist immer noch [1,2,3], da es eine andere Referenz hat.
Aber ich denke, in allen oben genannten Methoden ist Array.from besser und hauptsächlich zum Kopieren eines Arrays gedacht .
quelle
Ich persönlich würde diesen Weg bevorzugen:
quelle
In meinem speziellen Fall musste ich sicherstellen, dass das Array intakt blieb, damit dies für mich funktionierte:
quelle
Kopie des mehrdimensionalen Arrays / Objekts erstellen:
Vielen Dank an James Padolsey für diese Funktion.
Quelle: Hier
quelle
Dan, du musst keine ausgefallenen Tricks anwenden. Sie müssen lediglich eine Kopie von arr1 erstellen.
Jetzt
arr1
undarr2
sind zwei verschiedene Array-Variablen in separaten Stapeln gespeichert. Überprüfen Sie dies auf jsfiddle .quelle
var arr2 = [arr1];
).Wenn wir ein Array mit dem Zuweisungsoperator (
=
) kopieren möchten, wird keine Kopie erstellt, sondern lediglich der Zeiger / Verweis auf das Array kopiert. Zum Beispiel:Wenn wir Daten transformieren, möchten wir häufig unsere ursprüngliche Datenstruktur (z. B. Array) intakt halten. Dazu erstellen wir eine exakte Kopie unseres Arrays, damit dieses transformiert werden kann, während das ursprüngliche intakt bleibt.
Möglichkeiten zum Kopieren eines Arrays:
Seien Sie vorsichtig, wenn Arrays oder Objekte verschachtelt sind!:
Wenn Arrays verschachtelt sind, werden die Werte als Referenz kopiert. Hier ist ein Beispiel, wie dies zu Problemen führen kann:
Verwenden Sie diese Methoden also nicht, wenn sich Objekte oder Arrays in Ihrem Array befinden, die Sie kopieren möchten. dh Verwenden Sie diese Methoden nur für Arrays von Grundelementen.
Wenn Sie ein Javascript-Array tief klonen möchten, verwenden Sie Folgendes
JSON.parse
in Verbindung mitJSON.stringify
:Kopierleistung:
Welches wählen wir also für eine optimale Leistung? Es stellt sich heraus, dass die
for
Schleife als ausführlichste Methode die höchste Leistung aufweist. Verwenden Sie diefor
Schleife für wirklich CPU-intensives Kopieren (große / viele Arrays).Danach hat die
.slice()
Methode auch eine anständige Leistung und ist auch weniger ausführlich und für den Programmierer einfacher zu implementieren. Ich empfehle,.slice()
für das tägliche Kopieren von Arrays zu verwenden, die nicht sehr CPU-intensiv sind. Vermeiden Sie auch die Verwendung vonJSON.parse(JSON.stringify(arr))
(viel Overhead), wenn kein tiefer Klon erforderlich ist und die Leistung ein Problem darstellt.Quellleistungstest
quelle
Wenn Ihr Array Elemente des primitiven Datentyps wie int, char oder string usw. enthält , können Sie eine dieser Methoden verwenden, die eine Kopie des ursprünglichen Arrays zurückgeben, z. B. .slice () oder .map () oder einen Spread-Operator ( dank ES6).
oder
oder
ABER wenn Ihr Array komplexe Elemente wie Objekte (oder Arrays) oder mehr verschachtelte Objekte enthält , müssen Sie sicherstellen, dass Sie eine Kopie aller Elemente von der obersten Ebene bis zur letzten Ebene erstellen, sonst Referenz des Inneren Objekte werden verwendet und das bedeutet, dass das Ändern von Werten in object_elements in new_array weiterhin Auswirkungen auf das old_array hat. Sie können diese Kopiermethode auf jeder Ebene als TIEFKOPIE bezeichnen des old_array bezeichnen.
Für das Tiefenkopieren können Sie die oben genannten Methoden für primitive Datentypen auf jeder Ebene je nach Datentyp verwenden, oder Sie können diese kostspielige Methode (siehe unten) zum Erstellen einer Tiefenkopie verwenden, ohne viel Arbeit zu leisten.
Es gibt viele andere Methoden, die Sie je nach Ihren Anforderungen anwenden können. Ich habe nur einige davon erwähnt, um eine allgemeine Vorstellung davon zu geben, was passiert, wenn wir versuchen, ein Array nach Wert in das andere zu kopieren .
quelle
Wenn Sie eine neue Kopie eines Objekts oder Arrays erstellen möchten, müssen Sie die Eigenschaften des Objekts oder der Elemente des Arrays explizit kopieren, z. B.:
Sie können bei Google nach weiteren Informationen zu unveränderlichen Grundwerten und veränderlichen Objektreferenzen suchen.
quelle
Die Verwendung von jQuery Deep Copy kann wie folgt erfolgen:
quelle
Sie können auch den ES6-Spread-Operator verwenden, um das Array zu kopieren
quelle
Hier sind einige weitere Möglichkeiten zum Kopieren:
quelle
Sie könnten ES6 mit Spread Opeartor verwenden, es ist einfacher.
Es gibt Einschränkungen. Überprüfen Sie die Dokumente. Spread syntax @ mozilla
quelle
Schnelle Beispiele:
quelle
Hier ist eine Variante:
quelle
toSource
kein Standard ist und beispielsweise in Chrome nicht funktioniert.Es gibt das neu eingeführte
Array.from
, aber leider wird es zum Zeitpunkt dieses Schreibens nur von neueren Firefox-Versionen (32 und höher) unterstützt. Es kann einfach wie folgt verwendet werden:Referenz: Hier
Oder
Array.prototype.map
kann mit einer Identitätsfunktion verwendet werden:Referenz: Hier
quelle
Array.from
, die jetzt von allen gängigen Browsern außer Internet Explorer ( Quelle ) unterstützt wird. .Array.from
werden Daten mutieren, nicht tief Kopieren / tief Klonen liefert.Für ES6-Arrays mit Objekten
quelle