Javascript: Arrays kopieren

Banale Aufgabe: Erstelle eine unabhängige Kopie von einem Javascript-Array. Was erstmal billig klingt entpuppt sich für unwissende, PHP verwöhnte Entwickler doch als tricky.

var colors = ["red", "blue", "green"];
var copied = colors;

copied[0] = "magenta";

console.log(colors); //["magenta", "blue", "green"]
console.log(copied); //["magenta", "blue", "green"]

In diesem Beispiel sehen wir also, dass die vermeintliche Kopie eigentlich das gleiche Element ist. Gleiches gilt entsprechend für das Übergeben eines Arrays als Parmeter an eine Funktion.

var colors = ["red", "blue", "green"];

test(colors);
console.log(colors); //["magenta", "blue", "green"]

function test(arr)
{
	arr[0] = "magenta";
}

Offensichtlich nicht wie von PHP gewohnt By Value sondern By Reference.

Ja und wie geht es nun?

Enter Array.slice. Damit lassen sich wirkliche Kopien erstellen.

var colors = ["red", "blue", "green"];
var colorscopy = colors.slice(); //or colors.slice(0, colors.length);

colorscopy[0] = "magenta";

console.log(colors); //["red", "blue", "green"]
console.log(colorscopy); //["magenta", "blue", "green"]

Tada! Als Alternative könnte man sich auch selbst was zusammenbasteln, etwa so:

for (var i in original) {
	copy[i] = original[i];
}

Wer cool ist und / oder mit der Bezeichnung slice nicht klarkommt, kann es auch elegant per Prototyp lösen:

Array.prototype.copy = function() 
{
	return this.slice();
}

var colors = ["red", "blue", "green"];
var colorscopy = colors.copy();
//...

[Ergänzung: So cool scheint das doch nicht zu sein…

One mis-feature that is often used is to extend Object.prototype or one of the other built in prototypes.

This technique is called monkey patching and breaks encapsulation. While used by widely spread frameworks such as Prototype, there is still no good reason for cluttering built in types with additional non-standard functionality.

Außerdem bekommt man so Probleme mit for-in-Loops, bei denen dann auch die Funktion aus dem Prototyp mit auftaucht (danke an Steffen).

(Quelle)]

Hätten wir das also abgehakt. Aber es gibt noch einen…

Bonus! Arraygröße erweitern und verkürzen

Javascript Arrays verlängern sich ganz bequem, indem sie den Zwischenraum mit undefined ausfüllen:

var colors = ["red", "blue", "green"];
colors[7] = "yellow";

alert(colors.length); //8
console.log(colors);
//["red", "blue", "green", undefined, undefined, undefined, undefined, "yellow"]

Was viele nicht wissen: Array.length ist nicht readonly. Damit lassen sich Arrays auch verkürzen (allerdings nicht verlängern):

var colors = ["red", "blue", "green"];
colors.length = 2;
console.log(colors);
//["red", "blue"]

Falls es mal jemand gebrauchen sollte.

[Ergänzung 2:

var copied = [].concat(original);

Ein weiterer geschmeidiger Weg, um ein Array zu kopieren (danke an Fabian).]

Weitere Posts:

Dieser Beitrag wurde unter Javascript, webdev veröffentlicht. Setze ein Lesezeichen auf den Permalink.

7 Antworten auf Javascript: Arrays kopieren

  1. Fabian sagt:

    Offensichtlich nicht wie von PHP gewohnt By Value sondern By Reference.

    Genaugenommen sind Arrays in JavaScript eben auch Objekte und leider gibt es keine native clone Funktion.

    Eine andere Lösung die ich zum Kopieren von Arrays gefunden habe ist folgende:

    copied = [].concat(original)

    1. david sagt:

      Cool, danke für die Ergänzung.

  2. Ergänzung zur Ergänzung: wenn man den Prototyp des Arrays erweitert, bekommt man Probleme mit foreach Schleifen – die liefern nämlich das neue Prototype-Element auch mit:


    for (var index in myarray) {
    alert(index + ": " + myarray[index]); // Hier kommt dann auch "copy: function" mit!
    }

    1. david sagt:

      Recht haste, danke!

      Wie meine neue Lieblingsseite empfiehlt, sollte man in for-in Loops immer mit hasOwnProperty arbeiten:

      It is also recommended to make hasOwnProperty part of every for in loop, this will avoid errors from extended native prototypes.

      Dann klappts auch mit dem Nachbarn ;)


      Array.prototype.copy = function()
      {
      return this.slice();
      }

      var colors = ["red", "blue", "green"];
      var colorscopy = colors.copy();

      for (var index in colorscopy)
      {
      if (colorscopy.hasOwnProperty(index))
      console.log(index + ": " + colorscopy[index]);
      }

  3. equu sagt:

    „Javascript: Arrays von Primitivdatentypen kopieren“ sollte dieser Beitrag lauten, wie folg. Codeabschnitt mit Objekten zeigt:

    var colors = [{a:1}, {a:2}, {a:3}];
    var colorscopy = [].concat(colors);
    colorscopy[0].a = 11;

    Viele Grüße
    Equu

  4. Sebastian Prodan sagt:

    Cool, danke für den Beitrag
    hilft auch 4 Jahre danach :eek!

  5. Tristan Tate sagt:

    Mit den Erweiterungen des ECMA scripts wird die Verwendung von var nicht mehr empfohlen.
    Die Funktionen map, reduce, Filter und concat sowie slice sind nach wie vor gute und kurze Möglichkeiten, deep copies bzw echte kopien zu erstellen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert