Bitte lesen Sie den folgenden Code und erraten Sie das Ausführungsergebnis:
var start = new Datum; setTimeout (function () {console.log ('Zeit vergibt:'+(neues Datum - Start)+'msc');}, 200); while (neues Datum - Start <1000) {} console.log (1); Funktion doSoming () {setTimeout (function () {console.log ('Zeit wird erneut übergeht:'+(neues Datum - Start)+'msc');}, 10);} dosoming (); while (neues Datum - Start <2000) {} console.log (2);sich herausstellen:
Ausgabe nach ca. 1 Sekunde: 1,
Nach ca. 1 Sekunde ist die Ausgabe: 2.
Dann sofort ausgeben: Zeit vergangen: 2002 Millisekunden
Letzte Ausgabe: Die Zeit wurde erneut verabschiedet: 2003 Millisekunden
Hast du es richtig erraten?
Hier werden alle Funktionen, die die Ausführung nach SetTimeout verzögern, vor der Ausführung bis zum Ende gedrängt.
Das Prinzip ist wie folgt:
In der vorhandenen Browserumgebung ist die JavaScript-Ausführungsmaschine Single-Thread. Die Aussagen und Methoden des Hauptfadens blockieren den Lauf der Zeitaufgaben. Außerhalb der JavaScript -Ausführungs -Engine gibt es eine Task -Warteschlange. Wenn die SetTimeOut () -Methode im Code aufgerufen wird, wird die registrierte Verzögerungsmethode zur Verarbeitung an andere Module im Browserkernel aufgehängt. Wenn die Verzögerungsmethode die Auslöserbedingung erreicht, dh die festgelegte Verzögerungszeit erreicht den Satz, fügt das Modul die zu ausgeführte Methode in die Task -Warteschlange des Moduls hinzu. Dieser Prozess ist unabhängig vom Hauptfaden der Ausführungsmaschine. Die Ausführungs -Engine extrahiert Aufgaben aus der Task -Warteschlange des Moduls nach Ausführung, wenn die Haupt -Thread -Methode ausgeführt wird und den Leerlaufstatus erreicht. Die Zeit in diesem Zeitraum kann größer sein als die Verzögerungszeit bei der Registrierung der Aufgabe.
Wenn der Browser im Leerlauf ist, wird ständig versucht, Aufgaben aus der Task -Warteschlange des Moduls zu extrahieren, die als Ereignisschleifmodell bezeichnet wird.
Schauen wir zurück auf den vorherigen Code. Die Verzögerungszeit der zweiten SetTimeout () -Deladungsmethode beträgt 10 Millisekunden, die früher als die erste ausgelöst wird! Warum ist das Ausführungsergebnis dahinter? Da es durch den vorherigen Code für etwa 1000,5 ~ 1001 Millisekunden (abhängig von der Verarbeitungsgeschwindigkeit des Browsers) blockiert wurde, hängt es beim Aufgabenwettbewerb, wenn es an das Verarbeitungsmodul hängt und die Auslöserzeit hinzugefügt wird, dem Task -Team des Moduls des Moduls, und das Haupttotor -Thread wird erhalten, und Sie sollten sich in der Reihenfolge erhalten, wie Sie es verstehen sollten.
Wenn Sie nun die oben genannte Zeit ändern (neues Datum - Start <1000) {} auf while (neues Datum - Start <189) {} oder while (neues Datum - Start <190) {}, was ist das Ergebnis? Ich werde nicht viel sagen! Aktualisieren Sie den Browser 20 Mal jeweils und sehen Sie die Ergebnisse selbst!
Die setInterval () -Methode und setTimeout () haben den gleichen Status. Wenn die setInterval () -Methode aufgerufen wird, wird die registrierte Verzögerungsmethode zur Verarbeitung an das Modul aufgehängt. Wenn die Auslöserzeit eintrifft, wird die zu ausgeführte Methode der Task -Warteschlange einmal hinzugefügt.
Schauen wir uns die Syntax von SetTimeout an:
var timeId = window.settimeout (func, delay, [param1, param2, ...]);
var timeId = window.settimeout (Code, Verzögerung);
SetTimeout und SetInterval sind Methoden von Fensterobjekten (Fenster können weggelassen werden). Die zweiten optionalen Parameter (nicht von IE9 und alten Versionen unterstützt) sind Parameter, die an den Func übergeben wurden. Jedes Mal, wenn sie aufgerufen werden, wird eine numerische ID zurückgegeben (es handelt sich nur um eine Nummer, die im Browser gedruckt ist, aber ich habe sie im Webstorm gedruckt und festgestellt, dass es sich tatsächlich um ein Objekt mit vielen Attributen handelt). Diese ID verwaltet die relevanten Informationen zu ihren entsprechenden SetTimeout oder SetInterval und wird hauptsächlich zum Löschen (oder Schließen) im mittleren Modul und in der Task -Warteschlange verwendet (unter Verwendung der Methoden Clearimeout (ID) und ClearInterval (ID)).
Wenn Sie einen Parameter in Ihre Rückruffunktion übergeben müssen, ist Folgendes die IE-kompatible Schreibmethode
if (document.all &&! window.settimeout.ispolyfill) {var __nativest__ = window.settimeout; window.settimeout = function (vcallback, ndelay, param1, param2, param3) {var aargs = array.prototype.slice.call (Argumente, 2); return __nativest __ (vcallback instanceof function? function () {vcallback.apply (null, aargs);}: vcallback, ndelay); }; window.settimeout.ispolyfill = true;}Bei der Verwendung von Schließungen in einer Schleife tritt ein häufiger Fehler auf
für (var i = 0; i <10; i ++) {setTimeout (function () {console.log (i);}, 1000);}Der obige Code gibt die Nummer 10 zehnmal aus. Warum? Schließung!
Wenn Console.log aufgerufen wird, ist die anonyme Funktion, obwohl eine Verweise auf die externe Variable I beibehält, die für die Schleife zu diesem Zeitpunkt beendet und der Wert von I wird auf 10 geändert.
Um das gewünschte Ergebnis zu erzielen, muss eine Kopie der Variablen, die ich in jeder Schleife erstellt werden muss.
Um die Schleifennummer korrekt zu erhalten, verwenden Sie am besten eine anonyme Wrapper (tatsächlich nennen wir normalerweise selbst extra anonyme Funktionen).
für (var i = 0; i <10; i ++) {(Funktion (e) {setTimeout (function () {console.log (e);}, 1000);}) (i);}Die externe anonyme Funktion wird sofort ausgeführt und ich werde als Parameter verwendet. Zu diesem Zeitpunkt hat die E -Variable in der Funktion eine Kopie von i.
Wenn die anonyme Funktion an SetTimeout ausgeführt wird, hat sie einen Verweis auf E, und dieser Wert wird nicht durch die Schleife geändert.
Es gibt eine andere Möglichkeit, den gleichen Job zu machen. Das heißt, eine Funktion aus einer anonymen Wrapper zurückzugeben. Dies funktioniert genauso wie der obige Code.
für (var i = 0; i <10; i ++) {setTimeout ((Funktion (e) {return function () {console.log (e);}}) (i), 1000)}Eine weitere wichtige Anwendung: Funktionsdrossel und Funktion entdecken
Bitte beachten Sie einige Informationen, die ich aus dem Internet gesammelt habe:
JavaScript - Funktionsoptimierungsfunktion Drossel und Funktion Downounce
Referenzlink:
https://developer.mozilla.org/zh-cn/docs/web/api/window/settimeout
http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout-said-the-event-loop-model/#prettyphoto
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.