Schleifen sind einer der wichtigsten Mechanismen in allen Programmiersprachen, und Schleifen sind in fast keinem Computerprogramm mit praktischer Bedeutung (Sortieren, Abfragen usw.) geöffnet. Looping ist auch ein sehr problematischer Bestandteil der Programmoptimierung. Wir müssen oft die Komplexität des Programms ständig optimieren, aber wir sind in der Auswahl zwischen Zeitkomplexität und Raumkomplexität aufgrund des Schleifens verwickelt.
In JavaScript gibt es 3 native Schleifen für () {}, while () {} und do {} while (), und die am häufigsten verwendeten sind für () {}.
Denn ist jedoch die wahrscheinlichste Schleife, die JavaScript -Ingenieure bei der Optimierung von Programmen ignorieren.
Lassen Sie uns zunächst das Grundkenntnis von für.
Die für die Syntax von JavaScript wird aus der C -Sprache geerbt, und es gibt zwei Möglichkeiten, die grundlegende Syntax von für Schleifen zu verwenden.
1. Looping Array
Grundlegende Syntax von für Schleife
Die Codekopie lautet wie folgt:
für ( / * Initialisierung * /2 / * Urteilsbedingung * /2 / * Loop -Verarbeitung * /) {
// ... logischer Code
}
Wir werden ausführlich einen Instanzcode erklären.
Die Codekopie lautet wie folgt:
var Array = [1, 2, 3, 4, 5];
var sum = 0;
für (var i = 0, len = array.length; i <len; ++ i) {
sum += array [i];
}
console.log ('die Summe der Array/' s its %d. ', sum);
// => Die Summe der Artikel des Arrays beträgt 15.
In diesem Code definieren und initialisieren wir zuerst ein Array, das die zu akkumulierten Elemente und eine Summenformierungsvariable speichert. Als nächstes beginnen wir die Schleife. Im Initialisierungscode für Schleife definieren und initialisieren wir auch zwei Variablen: I (Zähler) und Len (Alias der Loop -Array -Länge). Wenn ich weniger als Len ist, wird die Schleifenbedingung festgelegt und der logische Code ausgeführt. Nachdem jeder logische Code ausgeführt wurde, werde ich um 1 erhöht.
Im logischen Code der Schleife fügen wir den Summenvariablen die Array -Begriffe der aktuellen Schleife hinzu.
Dieser Zyklus wird wie folgt durch das Flussdiagramm dargestellt:
Aus diesem Flow -Diagramm ist es nicht schwer zu ermitteln, dass der reale Schleifenkörper im Programm nicht nur unseren logischen Code enthält, sondern auch die Ausführungsurteils- und Schleifenverarbeitung enthält, die die Schleife selbst implementiert.
Auf diese Weise werden unsere Optimierungsideen klar sein und wir können aus vier Aspekten optimieren.
1. Initialisierungscode vor dem Schleifenkörper
2. Bedingungen für Ausführungsbeurteilungen im Schleifenkörper
3.. Logischer Code
4.. Code nach logischem Code verarbeiten
PS: Es gibt eine wichtige Beziehung zwischen dem ersten und dem zweiten Punkt.
1.1 Initialisierungscode und Ausführungsbeurteilungsbedingungen optimieren
Schauen wir uns zunächst einen Code an, mit dem jeder sehr vertraut ist.
Die Codekopie lautet wie folgt:
// falsch!
für (var i = 02 i <list.length2 ++ i) {
// ... logischer Code
}
Ich glaube, dass die meisten Ingenieure, die JavaScript schreiben, diese scheinbar normale Schleifenmethode immer noch verwenden, aber warum sage ich, dass es hier falsch ist?
Nehmen wir alles in dieser Schleife auseinander und schauen wir uns an:
1. Initialisieren Sie Code - Diese Schleife definiert und initialisiert nur eine Gegenvariable.
2. Ausführungsurteilsbedingung - Es ist wahr, wenn der Zähler geringer ist als die Länge der Liste.
3. Verarbeitungscode - Der Zähler wird durch 1 erhöht.
Lassen Sie uns das obere Flussdiagramm überprüfen und herausfinden, ob etwas daran falsch ist?
Der Real Loop -Körper hat nicht nur unseren logischen Code, sondern enthält auch den Ausführungsurteils- und Verarbeitungscode, der die Schleife selbst implementiert. Mit anderen Worten, die Urteilsbedingung i <list.Length muss vor jeder Schleife ausgeführt werden. In JavaScript ist eine Abfrage erforderlich, wenn die Eigenschaften oder Methoden eines Objekts gelesen werden.
Sie scheinen etwas zu verstehen, oder? In dieser Beurteilungsbedingung gibt es zwei Operationen: 1. Fragen Sie das Längenattribut aus dem Listenarray ab; 2. Vergleichen Sie die Größen von i und list.length.
Unter der Annahme, dass das List -Array N -Elemente enthält, muss das Programm 2N -Operationen im Ausführungsurteil dieser Schleife durchführen.
Wenn wir den Code dazu ändern:
Die Codekopie lautet wie folgt:
// Also
für (var i = 0, len = list.length; i <len; ++ i) {
// ...
}
In diesem verbesserten Code haben wir eine Definition hinzugefügt und eine LEN -Variable initialisiert, um den Wert der Liste der Liste zu speichern. Auf diese Weise müssen wir das List -Array im Ausführungsurteil im Schleifenkörper nicht erneut abfragen, und der Operand ist die Hälfte des ursprünglichen.
In den obigen Schritten haben wir die zeitliche Komplexität des Algorithmus verbessert, und wie sollten wir das tun, wenn wir die Raumkomplexität weiter optimieren möchten? Wenn Ihr Logikcode nicht durch Schleifenbestellung begrenzt ist, können Sie die folgende Optimierungsmethode ausprobieren.
Die Codekopie lautet wie folgt:
für (var i = list.length -1; i> = 0; --i) {
// ...
}
Dieser Code wird weitergeleitet, indem die Loop -Bestellung invertiert wird, beginnend mit dem letzten Element -Index (List.Length - 1). Um die Anzahl der für die Schleife erforderlichen Variablen auf 1 zu reduzieren, und im Ausführungsurteil wird die Anzahl der variablen Abfragen reduziert und die Zeit, die vor der Ausführung der CPU -Anweisung aufgewendet wird, wird reduziert.
1.2 Logikcode optimieren
In einer Schleife erhalten wir das aktuelle Array -Element der Schleife natürlich, um einige Operationen zu erledigen oder es zu verwenden, was zwangsläufig zu mehreren Aufrufen des Elements führt.
Die Codekopie lautet wie folgt:
var array = [
{Name: 'Will Wen Gunn', Typ: 'Hentai'},
{Name: 'Vill Lin', Typ: 'Moegril'}
];
für (var i = array.length -1; i> = 0; --i) {
console.log ('name: %s', array [i] .name);
console.log ('er/sie ist ein (n) %s', Array [i] .type);
console.log ('/r/n');
}
/*=>
Name: Vill Lin
Er/sie ist ein (n) Moegil
Name: Will wen Gunn
Er/sie ist ein (n) Hentai
*/
In diesem Code muss das Programm den Namen und die Attribute jedes Array -Elements abfragen. Wenn das Array n Elemente hat, führt das Programm 4N -Objektabfragen aus.
Die Codekopie lautet wie folgt:
1. Array [i]
2. Array [i] .Name
3.. Array [i]
4. Array [i] .typ
Ich glaube, Sie müssen zu diesem Zeitpunkt an eine Lösung nachgedacht haben, dh dem Wert des aktuellen Array -Elements einer Variablen und dann im logischen Code verwenden.
Die Codekopie lautet wie folgt:
var array = [
{Name: 'Will Wen Gunn', Typ: 'Hentai'},
{Name: 'Vill Lin', Typ: 'Moegril'}
];
var person = null;
für (var i = array.length -1; i> = 0 && (Person = Array [i]); --i) {
console.log ('name: %s', Person.name);
console.log ('er/sie ist ein (n) %s', Person.typ);
console.log ('/r/n');
}
Person = null;
Das sieht viel schöner aus.
Die Codekopie lautet wie folgt:
1. Array [i] => var Person Person
2. Person.Name
3. Person.Type
Es ist ein bisschen wie der Foreach in Emcascript5, aber der Unterschied zwischen den beiden ist riesig, also werde ich es hier nicht erklären.
PS: Vielen Dank für Ihre Korrektur. Nach den Experimenten stellte ich fest, dass, wenn die Elemente im Array durch direktes Bestehen der Werte definiert werden, der in der Schleife erhaltene Wert ein Wert sein muss, kein Zeiger. Egal, ob Sie Ausdrücke oder Variablen definieren, es gibt zusätzliche Speicherplatzanforderungen.
1.3 Optimieren Sie den Verarbeitungscode
Tatsächlich gibt es nicht viel, um den Verarbeitungscode im Schleifenkörper zu optimieren, und der I -Zähler reicht aus, um die 1 selbst zu erhöhen.
PS: Wenn Sie gute Vorschläge oder Methoden haben, geben Sie diese bitte an. :)
2. Zirkularobjekt (Objekt)
In JavaScript kann auch die Eigenschaften und Methoden des Objekts durchqueren. Es ist zu beachten, dass die für die Schleife nicht durch den Wickeltyp gehen kann, zu dem das Objekt gehört, oder die Prototyp -Eigenschaften und -Methoden im Konstruktor.
Die Syntax ist einfacher als Looping -Arrays.
Die Codekopie lautet wie folgt:
für (/* initialisieren*/ var Schlüssel im Objekt) {
// ... logischer Code
}
Wir verwenden diese Methode häufig, um Objekte zu betreiben.
Die Codekopie lautet wie folgt:
var person = {
'Name': 'Will wen Gunn',
'Typ': 'Hentai',
"Fertigkeit": ["Programmierung", "Fotografie", "Sprechen", "usw.]]
};
für (var key persönlich) {
value = Person [Schlüssel];
// Wenn der Wert ein Array ist, konvertieren Sie ihn in eine Zeichenfolge
if (Wertinstanz von Array) {
value = value.join (',');
}
console.log (' %s: %s', Schlüssel, Wert);
}
/*=>
Name: Will wen Gunn
Typ: Hentai
Fähigkeit: Programmierung, Fotografie, Sprechen usw.
*/
Wenn Sie MongoDB verwendet haben, werden Sie auf jeden Fall mit dem Abfragemechanismus vertraut sein. Da der Abfragemechanismus von MongoDB wie die Seele seiner API ist, hat die flexible Curd -Operation -Methode MongoDB viel Popularität und Entwicklungsimpulsion gewonnen.
In der Mongo -API -Implementierung von NanodB verwendet die Abfrageimplementierung Schleifenobjekte in großem Maßstab.
Die Codekopie lautet wie folgt:
var mydb = nano.db ('mydb');
var mycoll = mydb.collection ('mycoll');
var _cursor = mycoll.find ({{
Typ: 'Repo',
Sprache: 'JavaScript'
});
_Cursor
.Sortieren({
Stern: 1
})
.toArray (Funktion (Err, Zeilen) {
if (ähm)
return console.Error (err);
console.log (Zeilen);
});
Was wir optimieren müssen, ist nicht die Schleife selbst, sondern die Optimierung der Objekte, die Sie durchlaufen müssen.
Beispielsweise sieht die Nanocollection -Klasse in Nanodb wie ein Array aus, das alle Elemente oder Objekte enthält und die ID des Elements als Schlüssel verwendet und dann die Elemente speichert.
Dies ist jedoch nicht der Fall. Schüler, die Unterstrich verwendet haben, sollten die Methode _.invert kennen. Dies ist eine ziemlich interessante Möglichkeit, die Schlüssel und Werte des übergebenen Objekts umzukehren.
Die Codekopie lautet wie folgt:
var person = {
'Name': 'Will wen Gunn',
'Typ': 'Hentai'
};
var _inverted = _.invert (Person);
console.log (_inverted);
/*=>
{
'Will wen Gunn': 'Name',,
'Hentai': 'Typ' '
}
*/
Wenn Sie ein Schleifenobjekt verwenden müssen, um die Werte bestimmter Eigenschaften des Objekts abzufragen, können Sie die folgende Methode ausprobieren.
Die Codekopie lautet wie folgt:
var person = {
'Name': 'Will wen Gunn',
'Typ': 'Hentai'
};
var name = 'Will wen Gunn';
var _inverted = _.invert (Person);
if (_inverted [name] === 'name') {
console.log ('gefangen!');
}
// => gefangen!
Es gibt jedoch nicht viel Optimierung für Objektabfrage, und alles muss auf den tatsächlichen Anforderungen beruhen. : P
Als nächstes schauen wir uns die beiden anderen Loops an, while () {} und do {} while (). Ich glaube, dass jeder Freund, der einen Informatikkurs erhalten hat, mit diesen beiden Zyklen vertraut sein wird. Der einzige Unterschied zwischen ihnen ist die logische Reihenfolge der Ausführung des Schleifenkörpers.
Die Ausführungsreihenfolge von while () {} ähnelt der von für () {}. Ausführungsurteile werden vor dem logischen Code durchgeführt, der Initialisierungs- und Verarbeitungscode werden jedoch weggelassen.
Wenn eine Bedingung angegeben wird, wird der logische Code ausgeführt, bis die Bedingung nicht mehr gilt.
Die Codekopie lautet wie folgt:
var sum = 0;
while (sum <10) {
Summe + = Summe + 1;
}
console.log (sum);
// => 15
Do {} while () setzt das Ausführungsurteil nach dem logischen Code ein, was "zuerst tot und dann spielen" bedeutet.
Die Codekopie lautet wie folgt:
var sum = 0;
Tun {
Summe + = Summe + 1;
} while (sum <10);
console.log (sum);
// => 15
While () {} und do {} while () benötigen auch keinen Zähler, sondern verwenden bestimmte Bedingungen, um festzustellen, ob logische Code ausgeführt oder weiter ausgeführt werden soll.
3. While () {} und do {} while ()
while () {} und do {} while () werden hauptsächlich in der Geschäftslogik verwendet, und eine Reihe von Operationen werden kontinuierlich ausgeführt, um einen bestimmten Zweck zu erreichen, wie z. B. Task -Warteschlangen.
Diese beiden Schleifen sind jedoch gefährlich, da sie standardmäßig nur durch Ausführungsbedingungen kontrolliert werden. Wenn es keinen Einfluss auf das Ausführungsurteil im logischen Code hat, tritt eine tote Schleife auf.
Die Codekopie lautet wie folgt:
var sum = 02
// Warnung!
while (sum <10) {
sum = 1 + 12
}
Ein solcher Code unterscheidet sich nicht von der Zeit (true) {}. Vor der Verwendung müssen die Ausführungsbedingungen und die Auswirkungen auf die Ausführungsbedingungen geklärt werden.
V.
Ich glaube, dass alle JavaScript -Ingenieure Break -Aussagen verwendet haben, aber weiterhin relativ selten verwendet werden. Tatsächlich gibt es viele hervorragende JavaScript -Open -Source -Projekte, die gefunden werden können.
Um die Funktion der Anweisung für die Weitergabe zu lösen, schauen wir uns zuerst den Beispielcode an
Die Codekopie lautet wie folgt:
// node.js Broadcast Server
var net = require ('net');
var util = require ('util');
var BroadcastServer = net.createServer ();
// Client Store
BroadcastServer.clients = [];
// Clients Broadcast -Methode
net.socket.prototype.broadcast = function (msg) {
var Clients = BroadcastServer.clients;
// Holen Sie sich den Einweis des Broadcast -Clients in der zentralisierten
var index = clients.indexof (this);
für (var i = Clients.length -1; i> = 0; --i) {
if (i === Index) {
// Wenn es sich um einen Rundfunk -Client handelt, wird die aktuelle Schleifekörper beendet
weitermachen;
}
Currclient = Clients [i];
if (! currclient.destroyed) {
Currclient.write (
util.format (
'/r [Echo Client %s: %d] %s/ninput:',
currclient.remoteaddress, currclient.remoteport, msg)
);
}
}
};
// ein neu angeschlossener neuer Client
BroadcastServer.on ('Verbindung', Funktion (Client) {
BroadcastServer.clients.push (Client);
// Willkommen
client.write ('[Broadcast Server] Willkommen!/Ninput:');
Client.Broadcast (Client, beigetragen! ');
// Nachricht Handle
Client.on ('Data', Funktion (msg) {
Client.Broadcast (MSG);
client.write ('/rinput:');
});
// Die Verbindung des Griffs trennen
client.on ('end', function () {
Client.Broadcast ('links!');
})
});
// binden
BroadcastServer.Listen (8080, function () {
console.log ('Broadcast Server gebunden.');
});
Dieser Code implementiert einen Broadcast -Server basierend auf dem Netzmodul node.js. In der Broadcast -Methode verwenden wir die Anweisung Continual, um alle verbundenen Clients zu implementieren, die Verbindungen mit Ausnahme des Broadcast -Clients hergestellt haben.
Der Codeinhalt ist recht einfach. Wenn ein Kunde an andere Clients übertragen wird, wird die Broadcast -Methode des entsprechenden Client -Objekts zum Client aufgerufen. In der Broadcast -Methode wird das Programm zunächst den Positions -Einweis des aktuellen Clients in der Cached Client Socket Collection erhalten und dann alle Client -Sockets durchlaufen. Wenn der Schleifenschalter das zuvor erhaltene Positionstell erreicht, wird der logische Code in der aktuellen Schleifenkörper übersprungen und die nächste Schleife wird fortgesetzt.
Ich glaube, dass Ingenieure, die die C/C ++ - Sprache gelernt haben, diesen Rat von verschiedenen Orten erhalten: "Verwenden Sie keine GOTO -Aussagen."
Diese "berüchtigte" GOTO -Anweisung ist tatsächlich ein Code -Flow -Controller, und die Details der GOTO -Anweisung werden hier nicht ausführlich erklärt. Es gibt jedoch keine offensichtliche GOTO -Aussage in JavaScript, aber aus Break -Aussagen und weiteren Aussagen ist es nicht schwierig, den Schatten von GOTO in JavaScript zu finden.
Dies liegt daran, dass Break -Anweisungen und Fortsetzung Anweisungen die Annahme eines definierten Label -Namens für die Umleitung von Code ermöglichen.
Schauen wir uns den von MDN bereitgestellten Beispielcode an.
Die Codekopie lautet wie folgt:
var i, j;
Loop1:
für (i = 0; i <3; i ++) {// Die erste für die Anweisung wird als "Loop1" bezeichnet.
Loop2:
für (j = 0; j <3; j ++) {// Die zweite für die Anweisung wird als "Loop2" bezeichnet.
if (i == 1 && j == 1) {
SOP1 fortsetzen;
} anders {
console.log ("i =" + i + ", j =" + j);
}
}
}
// Ausgabe ist:
// "i = 0, j = 0"
// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// "i = 2, j = 0"
// "i = 2, j = 1"
// "i = 2, j = 2"
// Beachten Sie, wie es sowohl "i = 1, j = 1" als auch "i = 1, j = 2" überspringt.
In diesem Beispielcode werden zweischichtige Schleifen implementiert, und außerhalb jeder Schleife wird eine Etikette definiert, die zum Aufrufen der nachfolgenden Anweisung für die Weitergabe verwendet wird.
Die erste Schleifeschicht befindet sich in der Etikett von Loop1, dh im nachfolgenden Programm, wenn die Schleife1 -Etikett in der Anweisung für die Anweisung für die Weitergabe oder Break ausgewählt wird, wird die äußerste Schleife brechen.
Die zweite Schichtschleife befindet sich in der Etikett von Loop2 in der oberen Schleife. Wenn das Loop2-Etikett in der Anweisung für die Weitergabe oder Break ausgewählt ist, kehrt sie zum Schleifenkörper der oberen Schleife zurück.
Durch die Verwendung von Schleifensteuerungsanweisungen können wir das ursprüngliche Urteilsvermögen der Loop -Ausführung beeinträchtigen, damit ein sehr komplexes Logiksystem erstellt werden kann. Um es unverblümt auszudrücken, es gibt viele GOTO -Aussagen im Linux -Kernel. Was immer noch oft Bemerkungen wie Goto -Aussagen hören, google sie einfach selbst.
5. Advanced Loop
5.1 die Schleife erweitern
Schauen wir uns zunächst die beiden Codestücke an und raten Sie mal, welches eine bessere Leistung hat.
Die Codekopie lautet wie folgt:
// Aufstellen
var array = [
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"],
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"],
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"],
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"],
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"],
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"],
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"],
["Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten", "Daten"]
];
Funktionsprozess (Element) {
// etwas mit Artikel mach
}
// Fall 1
für (var i = array.length-1; i> = 0; i--) {
für (var j = array [i] .Length-1; j> = 0; i--) {
Prozess (Array [i] [j]);
}
}
// Fall 2
für (var i = array.length - 1; i> = 0; i = i - 4) {
für (var j = array [i] .Length - 1; j> = 0; j = j - 6) {
Prozess (Array [i] [j]);
Prozess (Array [i] [j - 1]);
Prozess (Array [i] [j - 2]);
Prozess (Array [i] [j - 3]);
Prozess (Array [i] [j - 4]);
Prozess (Array [i] [j - 5]);
}
für (var j = array [i - 1] .Length - 1; j> = 0; j = j - 6) {
Prozess (Array [i] [j]);
Prozess (Array [i] [j - 1]);
Prozess (Array [i] [j - 2]);
Prozess (Array [i] [j - 3]);
Prozess (Array [i] [j - 4]);
Prozess (Array [i] [j - 5]);
}
für (var j = array [i - 2] .Length - 1; j> = 0; j = j - 6) {
Prozess (Array [i] [j]);
Prozess (Array [i] [j - 1]);
Prozess (Array [i] [j - 2]);
Prozess (Array [i] [j - 3]);
Prozess (Array [i] [j - 4]);
Prozess (Array [i] [j - 5]);
}
für (var j = array [i - 3] .Length - 1; j> = 0; j = j - 6) {
Prozess (Array [i] [j]);
Prozess (Array [i] [j - 1]);
Prozess (Array [i] [j - 2]);
Prozess (Array [i] [j - 3]);
Prozess (Array [i] [j - 4]);
Prozess (Array [i] [j - 5]);
}
}
Ich muss alle Elemente der Subtarray im Array durchgehen. Es gibt zwei Lösungen, eine ist die Methode, die wir normalerweise anwenden, und die andere besteht darin, die Schleifenaufgabe zu erweitern. Die Antwort ist, dass Fall 2 besser funktioniert, da alle Ausführungsurteile zwischen 6 Elementen gelöscht werden, was von Natur aus schneller als gewöhnlich ist.
Hier werfen wir einen Blick auf eine leistungsstärkere Lösung. Wenn ein Geschäftsverbindung iterativ auf einem großen Datensatz verarbeitet werden muss und das Datenvolumen von Beginn der Iteration nicht ändert, können Sie eine Technologie in Betracht ziehen, die als Duff -Gerät bezeichnet wird. Diese Technologie ist nach ihrem Schöpfer Tom Duff benannt, der erstmals in der C -Sprache implementiert wurde. Später portierte Jeff Greenberg es mit JavaScript und modifizierte es durch Andrew b. King und schlug eine effizientere Version vor.
Die Codekopie lautet wie folgt:
// Kredit: Beschleunigen Sie Ihre Website (New Riders, 2003)
var iterations = math.floor (Werte.length / 8);
var Restover = Werte.Length % 8;
var i = 0;
if (Reste> 0) {
Tun {
prozess (Werte [i ++]);
} while (--Leftover> 0);
}
Tun {
prozess (Werte [i ++]);
prozess (Werte [i ++]);
prozess (Werte [i ++]);
prozess (Werte [i ++]);
prozess (Werte [i ++]);
prozess (Werte [i ++]);
prozess (Werte [i ++]);
prozess (Werte [i ++]);
} while (--Iterations> 0);
Das Arbeitsprinzip dieser Technik besteht darin, die durch 8 geteilte Wertelänge zu berechnen, um die Anzahl der Iterationen zu erhalten, die iteriert werden müssen, und die Mathematikfunktion zu verwenden.
Ich habe dieses Gerät verpackt und eine API mit einem asynchronen Geschmack erhalten.
Die Codekopie lautet wie folgt:
Funktion Duff (Array, Mapper) {
var n = math.floor (Array.length / 8);
var l = Array.Length % 8;
var i = 0;
if (l> 0) {
Tun {
Mapper (Array [i ++]);
} while (--i> 0);
}
Tun {
Mapper (Array [i ++]);
Mapper (Array [i ++]);
Mapper (Array [i ++]);
Mapper (Array [i ++]);
Mapper (Array [i ++]);
Mapper (Array [i ++]);
Mapper (Array [i ++]);
Mapper (Array [i ++]);
} while (--n> 0);
}
Duff ([...], Funktion (Element) {
// ...
});
Hier finden Sie eine Reihe von Leistungstests und Ergebnissen für die oben genannten drei iterativen Lösungen. http://jsperf.com/spreadede-loop
5.2 Nicht einheimische Schleife
In jeder Programmiersprache können Schleifen nicht nur indirekt auf andere Weise, sondern auch auf andere Weise implementiert werden.
Lassen Sie uns zunächst einige Inhalte der Mathematik der High School - der allgemeinen Formel der Sequenzen - überprüfen.
Die Codekopie lautet wie folgt:
Basic
a [1] = 1
a [n] = 2 * a [n - 1] + 1
Also
a [n] + 1 = 2 * a [n - 1] + 2
= 2 * (a [n - 1] + 1)
(a [n] + 1) / (a [n - 1] + 1) = 2
Dann
a [n] + 1 = (a [n] + 1) / (a [n - 1] + 1) * (a [n - 1] + 1) / (a [n - 2] + 1) * ... * (a [2] + 1) / (a [1] + 1) * (a [i] + 1)
a [n] + 1 = 2 * 2 * ... * 2 * 2
a [n] + 1 = 2^n
a [n] = 2^n - 1
Finale
a [n] = 2^n - 1
Nachdem Sie die obige einfache Berechnung gelesen haben, erraten Sie wahrscheinlich, was wir besprechen werden. Ja, wir können auch Schleifen mit Rekursion implementieren.
Rekursion ist eine sehr wichtige Anwendungsmethode in Mathematik und Informatik, die sich auf eine Funktion bezieht, die sich selbst aufruft, wenn sie verwendet wird.
In der Node.js -Community wird Rekursion verwendet, um eine sehr wichtige Technologie zu implementieren: Middleware -Technologie. Dies ist eine neue Version des Middleware -Implementierungscode in WebJs, die noch nicht veröffentlicht wurde.
Die Codekopie lautet wie folgt:
/**
* Middlewares Run -Methode
* @param {String} URL Aktuelle Anforderung URL
* @param {Object} Das Anforderungsobjekt requitiert
* @param {Object} res das Antwortobjekt res
* @param {function} out Complete Callback
* @return {function} Der Server
*/
server.runmiddlewares = function (url, req, res, out) {
var index = -1;
var Middlewares = this.useusingmiddlewares;
// Führen Sie die nächste Middleware aus, wenn sie existiert
Funktion Next (err) {
Index ++;
// aktuelle Middleware
var Curr = Middlewares [Index];
if (Curr) {
var check = new regexp (curr.route);
// Überprüfen Sie die Route
if (check.test (url)) {
versuchen {
Funktion später () {
Debugug ('A Middleware sagt, dass es später in %s', URL) sein muss;
// Die Abhängigkeiten tun derzeit nicht
if (MiddleWares.Indexof (Curr)! == Middlewares.length - 1) {
_later (Curr);
Index--;
nächste();
} anders {
Debugug ('A Middleware Depecies falsch');
// Diese Middleware kann nicht ausgeführt werden
aus();
}
}
// die Middleware ausführen
if (utils.isfunc (curr.handler)) {
// Normale Middleware -Funktion
Curr.Handler (Req, Res, Weiter, später);
} else if (utils.isObject (curr.handler) && utils.isfunc (Curr.handler.emit)) {
// Serverobjekt
Curr.handler.emit ('Anfrage', req, res, als nächstes, später);
} anders {
// Es stimmt etwas nicht an der Middleware
nächste();
}
} catch (err) {
nächste();
}
} anders {
nächste();
}
} anders {
// Aus dem nächsten Schritt der Pipeline
aus();
}
}
// Wenn die Middleware von anderen Middlewares abhängt,
// Es kann später laufen lassen
Funktion _later (Curr) {
var i = Middlewares.indexof (Curr);
var _tmp1 = Middlewares.lice (0, i);
_tmp1.push (Middlewares [i + 1], Curr);
var _tmp2 = Middlewares.lice (i + 2);
[] .push.apply (_tmp1, _tmp2);
MiddleWares = _tmp1;
}
// Erste Middleware
nächste();
gib dies zurück;
};
Obwohl dieser Code hart und kompliziert aussieht, wird er viel klarer, wenn wir ihn vereinfachen.
Die Codekopie lautet wie folgt:
server.runmiddlewares = function (url, req, res, out) {
var index = -1;
var Middlewares = this.useusingmiddlewares;
// Führen Sie die nächste Middleware aus, wenn sie existiert
Funktion Next (err) {
Index ++;
// aktuelle Middleware
var Curr = Middlewares [Index];
if (Curr) {
var check = new regexp (curr.route);
// Überprüfen Sie die Route
if (check.test (url)) {
// Führen Sie die aktuelle Middleware aus
Curr.Handler (Req, Res, Weiter);
} anders {
nächste();
}
} anders {
// Aus dem nächsten Schritt der Pipeline
aus();
}
}
// Erste Middleware
nächste();
gib dies zurück;
};
Der Grund, warum Rekursion bei der Implementierung des Middleware -Systems verwendet werden kann, ist, dass Rekursion die am besten geeignete Methode zur Programmablaufreaktion in Node.js.
In diesem Middleware -Implementierungscode ist dies.