2016-07-02 14 views
0

Ich spiele das schon eine Weile. Warum wird val_a geändert, wenn ich die Funktion zum Sortieren von val b ausführe? Wie kann ich das umgehen? Wenn ich die Funktion separat ausführe, funktionieren sie, aber wenn ich sie zusammen laufen lasse, läuft irgendwo etwas schief.Array.sort funktioniert nicht richtig, wenn zweimal aufgerufen?

var GLOBALS = {"items":[]}; 
 
var val_a; 
 
var val_b; 
 
GLOBALS.items=[ 
 
{"thing":"one","val_a":0.5,"val_b":0.2}, 
 
{"thing":"two","val_a":0.2,"val_b":0.3}, 
 
{"thing":"three","val_a":0.3,"val_b":0.1}]; 
 

 

 
\t val_a = GLOBALS.items.sort(function (a, b) { 
 
\t \t a=parseFloat(a.val_a); 
 
\t \t b=parseFloat(b.val_a); 
 

 
\t \t if (a < b) { 
 
\t \t \t return -1; 
 
\t \t } 
 
\t \t if (a > b) { 
 
\t \t \t return 1; 
 
\t \t } 
 
\t \t return 0; 
 
\t }); 
 

 
\t val_b = GLOBALS.items.sort(function (a, b) { 
 
\t \t a=parseFloat(a.val_b); 
 
\t \t b=parseFloat(b.val_b); 
 

 
\t \t if (a < b) { 
 
\t \t \t return -1; 
 
\t \t } 
 
\t \t if (a > b) { 
 
\t \t \t return 1; 
 
\t \t } 
 
\t \t return 0; 
 
\t }); 
 

 

 
\t console.log("val_a",val_a); 
 
\t console.log("val_b",val_b);

Antwort

5

Der Grund sehen Sie, was Sie sehen, ist, dass val_a und val_b nur Verweise auf das gleiche Array enthalten, die auch von GLOBALS.items verwiesen wird. sort ändert den Status des Arrays, auf das alle drei dieser Variablen zeigen.

Variablen enthalten Werte, keine Objekte. Wenn es sich um Objekte (einschließlich Arrays) handelt, ist der Wert in der Variablen eine Referenz zu dem Objekt, das tatsächlich an anderer Stelle im Speicher vorhanden ist. Stellen Sie sich diese Referenz als eine Zahl vor, die der JavaScript-Engine mitteilt, wo sich das Objekt an anderer Stelle im Speicher befindet. (Mehr unten.)

Wenn Sie drei separate Arrays (das Original items, dann eine Kopie von val_a sortiert, und eine andere sortiert nach val_b), möchten Sie eine flache Kopie des Arrays machen, bevor es das Sortieren, die Sie Sie kann mit slice:

val_a = GLOBALS.items.slice().sort(...); 

über das Array an anderer Stelle im Speicher zu sein, hier ist ein einfacheres Beispiel:

var a = [42]; // A variable with a reference to an array, which is 
       // elsewhere in memory 

der uns diese im Speicher gibt:

 
        +---------+ 
a<REF5512>--------->| (array) | 
        +---------+ 
        | 0: 42 | 
        +---------+ 

(Die REF5512 ist nur aus vollständig um den Punkt zu machen, der eine Referenz ein Wert ist. Wir sehen nie die rohen Referenzwerte)

Dann, wenn wir das tun.

var b = a; // A copy of that same reference 

der uns diese im Speicher gibt:

 
a<REF5512>---+ 
      |  +---------+ 
      +----->| (array) | 
      |  +---------+ 
b<REF5512>---+  | 0: 42 | 
        +---------+ 

Wenn wir den Zustand des Feldes ändern (zum Beispiel , indem es) sortiert wird, natürlich, dass Veränderungen sichtbar entweder variabel, da sie beide sind auf das gleiche Array:

b[0] = 67; 

gibt uns

 
a<REF5512>---+ 
      |  +---------+ 
      +----->| (array) | 
      |  +---------+ 
b<REF5512>---+  | 0: 67 | State of the array changed 
        +---------+ 

slice eine neue Array mit einer Kopie des Wertes in dem alten Array erzeugt (nur die Werte; Die Objekte in Ihrem Array werden nicht kopiert).So zum Beispiel:

b = a.slice(); 

Gibt uns:

 
        +---------+ 
a<REF5512>--------->| (array) | 
        +---------+ 
        | 0: 67 | 
        +---------+ 

        +---------+ 
b<REF7341>--------->| (array) | 
        +---------+ 
        | 0: 67 | 
        +---------+ 

Beachten Sie, wie die Referenz in b nicht mehr das gleiche wie in a ist.


Randbemerkung: Ihre sort Rückrufe viel einfacher sein:

val_a = GLOBALS.items.sort(function (a, b) { 
    return parseFloat(a.val_a) - parseFloat(b.val_a); 
}); 

Der sort Rückruf muss nur einen Wert zurückgeben kleiner als Null ist (es muss nicht sein, speziell -1), größer als Null (es muss nicht speziell 1 sein) oder gleich Null.

+1

Es sollte ein Abzeichen nur für Sie sein, genannt "The Flash: eine korrekte Antwort in weniger als 15 Sekunden liefern". –

+0

Für jetzt benutze ich das (wenn jemand auf das gleiche Problem läuft), aber ich will verstehen, was los ist. ' Funktion Quicksort (Daten, Schlüssel) { if (data.length == 0) return []; var left = [], rechts = [], pivot = Daten [0]; \t for (var i = 1; i data.length <; i ++) { if (data [i] [key] TeeraMusic

+0

@TeeraMusic: Sie müssen nicht Ihre eigene Art zu implementieren (obwohl natürlich Sie können), wie ich oben sagte, wenn Sie separate Arrays wollen, verwenden Sie einfach 'slice', um eine Kopie zu erstellen. Dieser 'Quicksort' erstellt Kopien (mehrere) des Arrays. –

Verwandte Themen