3 Stimmen

Effizienterer Vergleich von Zahlen

Ich habe ein Array, das Teil eines kleinen JS-Spiels ist, an dem ich arbeite. Ich muss (so oft wie vernünftig) überprüfen, dass keines der Elemente im Array die "Bühne" oder den "Spielplatz" verlassen hat, damit ich sie entfernen und die Skriptbelastung reduzieren kann.

Ich habe das Folgende programmiert und frage mich, ob jemand einen schnelleren/effizienteren Weg kennt, um dies zu berechnen. Dies wird alle 50ms ausgeführt (es handelt sich um die Bewegung).

Wo bots[i][1] die Bewegung in X darstellt und bots[i][2] die Bewegung in Y (ausschließlich) darstellt.

for (var i in bots) {
    var left = parseInt($("#" + i).css("left"));
    var top = parseInt($("#" + i).css("top"));
    var nextleft = left + bots[i][1];
    var nexttop = top + bots[i][2];
    if(bots[i][1]>0&&nextleft>=PLAYGROUND_WIDTH) { remove_bot(i); }
    else if(bots[i][1]<0&&nextleft<=-GRID_SIZE) { remove_bot(i); }
    else if(bots[i][2]>0&&nexttop>=PLAYGROUND_HEIGHT) { remove_bot(i); }
    else if(bots[i][2]<0&&nexttop<=-GRID_SIZE) { remove_bot(i); }
    else {
        //alert(nextleft + ":" + nexttop);
        $("#" + i).css("left", ""+(nextleft)+"px");
        $("#" + i).css("top", ""+(nexttop)+"px");
    }
}

In ähnlicher Weise ist die Funktion remove_bot(i); wie unten dargestellt. Ist das korrekt (ich kann nicht verändern, da sich alle IDs der Elemente im Array ändern).

function remove_bot(i) {
    $("#" + i).remove();
    bots[i] = false;
}

Vielen Dank für die gegebene Ratschläge!

8voto

Matt Punkte 72534
  1. Cache $("#" + i) in einer Variable; jedes Mal, wenn du das machst, wird ein neues jQuery-Objekt erstellt.

    var self = $('#' + i);
    var left = parseInt(self.css("left"));
    var top = parseInt(self.css("top"));
  2. Speichere bots[i] in einer Variable:

    var current = bots[i];
    var nextleft = left + current[1];
    var nexttop = top + current[2];
  3. Speichere (cache) das jQuery-Objekt des DOM-Elements innerhalb der Bot-Repräsentation. Im Moment wird es alle 50ms erstellt.

    Was ich damit meine ist, dass du für jede Iteration der Schleife $('#' + i) machst. Jedes Mal, wenn du das aufrufst, erstellt jQuery ein jQuery-Objekt des DOM-Elements. Dies ist im Vergleich zu anderen Aspekten von JS weit entfernt von trivial. Die DOM-Traversierung/ -Manipulation ist mit Abstand der langsamste Bereich von JavaScript.

    Da das Ergebnis von $('#' + i) für jeden Bot nie ändert, warum speicherst du nicht das Ergebnis im Bot? Auf diese Weise wird $('#' + i) einmal ausgeführt, anstatt alle 50ms.

    In meinem unten stehenden Beispiel habe ich diese Referenz im element-Attribut meiner Bot-Objekte gespeichert, aber du kannst es zu deinem Bot hinzufügen (z.B. in bots[i][3])

  4. Speichere (cache) die Position des DOM-Elements, das den Bot repräsentiert, innerhalb der Bot-Repräsentation, sodass die CSS-Position nicht ständig berechnet werden muss.

Übrigens sollte for (.. in ..) streng genommen nur zum Iterieren über Objekte verwendet werden, nicht über Arrays. Arrays sollten mit for (..;..;..) iteriert werden

Variablen sind in JavaScript extrem günstig; mach Gebrauch von ihnen.

Hier ist eine Implementierung, die ich wählen würde, die die Vorschläge, die ich gemacht habe, berücksichtigt:

function Bot (x, y, movementX, movementY, playground) {
    this.x = x;
    this.y = y;
    this.element = $('

1voto

Marcel Korpel Punkte 21267

Sie verwenden parseInt. Soweit ich weiß, ist ein Bitweises Oder 0 schneller als parseInt. Also könnten Sie schreiben

var left = $("#" + i).css("left") | 0;

stattdessen.

Darüber hinaus würde ich nicht jQuery-Funktionen verwenden, um Werte wie diese alle 50 ms zu erhalten, da immer mehr Overhead entsteht, wenn diese verwendet werden (die $ Funktion muss ihre Argumente analysieren, usw.). Verwenden Sie einfach native JavaScript-Funktionen, um diese Zeilen zu optimieren. Darüber hinaus muss das Element mit der ID i in Ihrem Code mehrmals abgerufen werden. Speichern Sie diese Elemente in einer Variablen:

var item = document.getElementById(i);
var iStyle = item.style;
var left = iStyle.left;
…

(Bitte beachten Sie, dass ich kein jQuery-Experte bin, daher bin ich mir nicht zu 100% sicher, ob dies dasselbe tut.)

Darüber hinaus sind abnehmende while-Schleifen schneller als for-Schleifen (Referenz). Wenn es keine Probleme gibt, die Elemente in umgekehrter Reihenfolge durchzugehen, könnten Sie Ihren Code umschreiben zu

var i = bots.length;
while (i--) {
    …
}

0voto

Tauren Punkte 26017

Werfen Sie einen Blick hier für einen großartigen Vergleich verschiedener Schleifen-Techniken in Javascript.

Die Verwendung von for...in hat eine schlechte Leistung und wird nicht für Arrays empfohlen. Eine Alternative zum Rückwärtsschleifen und dennoch Verwendung einer for-Schleife besteht darin, die Länge zu zwischenspeichern, damit Sie sie nicht bei jeder Iteration nachschlagen müssen. Etwas in der Art:

for(var i, len = bots.length; i < len; i++) { ... }

Aber es gibt VIELE verschiedene Möglichkeiten, wie im obigen Link gezeigt, und Sie sollten möglicherweise mehrere mit Ihrer tatsächlichen Anwendung testen, um zu sehen, was in Ihrem Fall am besten funktioniert.

0voto

Bob Punkte 7651

Verwenden Sie offset() oder position() je nachdem, ob Sie Koordinaten relativ zum Dokument oder zum Elternelement benötigen. position() ist wahrscheinlich schneller, da Browser effizient sind beim Finden von Offsetwerten relativ zum Elternelement. Es ist nicht notwendig, das CSS zu analysieren. Sie benötigen auch nicht die Variablen left und top, da Sie sie nur einmal verwenden. Es ist möglicherweise nicht so gut lesbar, aber Sie sind auf Effizienz ausgerichtet:

var left = $("#" + i).position().left + bots[i][1];
var top = $("#" + i).position().top + bots[i][2];

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