Ergänzender Artikel zur Front-End-Performance-Optimierung

Ergänzender Artikel zur Front-End-Performance-Optimierung

Vorwort

Ich habe mir die zuvor veröffentlichten Artikel zur Front-End-Leistungsoptimierung angesehen, einschließlich Standardschreibmethoden und Best Practices für JavaScript- und CSS- und jQuery-Programmierung zur Optimierung der Front-End-Leistung von Websites. Die Optimierung der Front-End-Leistung ist ein Prozess, der kontinuierlich verfolgt wird. Obwohl im vorherigen Artikel einige Leistungsoptimierungen erläutert wurden, ist die Leistungsoptimierung noch weit fortgeschritten und viele Dinge wurden nicht erwähnt. Heute werde ich, aufbauend auf den bisherigen Grundlagen, einige häufig verwendete Methoden zur Leistungsoptimierung kurz zusammenfassen.

Betreiber

1. Versuchen Sie bei der Verwendung von Operatoren, +=, -=, *=, \= und andere Operatoren zu verwenden, anstatt Zuweisungsoperationen direkt durchzuführen.

2. Bitoperation.

Bitoperationen sind bei der Durchführung mathematischer Operationen schneller. Bitoperationen sind schneller als alle Booleschen oder arithmetischen Operationen. Beispielsweise können auch Modulo, logisches UND und logisches ODER durch Bitoperationen ersetzt werden.

Ein Klassenkamerad fragte: „Was sind die gängigen bitweisen Operatoren in JS?“ Zu den gängigen Bitoperatoren gehören „~, &, |, ^, .<<, >>, >>>“ und so weiter.

Was ist die Verwendung und Funktion des einzelnen vertikalen Strichs „|“ des JS-Operators, den ich in früheren Artikeln im Hinblick auf die Anwendung von Bitoperationen erwähnt habe? Neben praktischen JavaScript- und JS-Kenntnissen können Sie es ausprobieren.

Allgemeine Optimierung
1. Switch-Anweisung.

Wenn Sie eine komplexe Reihe von if-else-Anweisungen haben, können Sie diese in eine einzelne switch-Anweisung umwandeln, um schnelleren Code zu erhalten. Sie können die Optimierung weiter optimieren, indem Sie die case-Anweisungen in der Reihenfolge von der wahrscheinlichsten zur unwahrscheinlichsten anordnen.

Zum Beispiel:

 Funktion getCategory(Alter) {
    var Kategorie = "";
    Schalter (wahr) {
        Fall ist NaN (Alter):
            Kategorie = "kein Alter";
            brechen;
        Fall (Alter >= 50):
            Kategorie = "Alt";
            brechen;
        Fall (Alter <= 20):
            Kategorie = "Baby";
            brechen;
        Standard:
            Kategorie = "Jung";
            brechen;
    };
    Rückgabekategorie;
}
getCategory(5); //Baby

In etwas komplizierteren Fällen wie diesem versuchen wir, if/else nicht zu verwenden. Für einfache Entscheidungen wird if/else natürlich trotzdem empfohlen.

2. Reduzieren Sie das Neuzeichnen von Seiten

Dieses Element wird in meinem jQuery-Artikel zur Optimierung erwähnt.

Der Code lautet wie folgt:

 var str = "<div>Dies ist eine Testzeichenfolge</div>";
/**Geringe Effizienz**/
var obj = document.getElementsByTagName("body");
für(var i = 0; i < 100; i++){
    obj.innerHTML += str + i;
}
/**Hohe Effizienz**/
var obj = document.getElementsByTagName("body");
var arr = [];
für(var i = 0; i < 100; i++){
    arr[i] = str + i;
}
obj.innerHTML = arr.join("");

3. Übergeben von Methoden anstelle von Methodenzeichenfolgen

Einige Methoden, wie etwa setTimeout() und setInterval(), akzeptieren Zeichenfolgen oder Methodeninstanzen als Parameter. Übergeben Sie das Methodenobjekt direkt als Parameter, um eine sekundäre Analyse der Zeichenfolge zu vermeiden.

Versandart

setTimeout(test, 1); //gut
Übergabemethode Zeichenfolge

setTimeout('test()', 1); //Kann nicht schlecht sagen, kann nur nicht gut sagen

4. Verwenden Sie primitive Operationen anstelle von Methodenaufrufen

Methodenaufrufe kapseln im Allgemeinen primitive Operationen. In Logik mit hohen Leistungsanforderungen können primitive Operationen anstelle von Methodenaufrufen verwendet werden, um die Leistung zu verbessern.

Ursprüngliche Bedienung

var min = a<b?a:b; //gut
Methodenbeispiele
var min = Math.min(a, b); // nicht gut

5. Zeitgeber

Wenn Sie auf Code abzielen, der kontinuierlich ausgeführt wird, sollten Sie nicht „setTimeout“, sondern „setInterval“ verwenden. setTimeout setzt jedes Mal einen Timer zurück.

6. Minimieren Sie die Anzahl der Anweisungen

Zum Beispiel:

Mehrere Variablendeklarationen

 /**Nicht empfohlen**/
var i = 1;
var j = "hallo";
var arr = [1,2,3];
var jetzt = neues Datum();
/**fördern**/
var i = 1,
    j = "hallo",
    arr = [1,2,3],
    jetzt = neues Datum();

Iterativer Wert einfügen

 /**Nicht empfohlen**/
var name = Werte[i];
ich++;
/**fördern**/
var name = Werte[i++];

Verwenden Sie Array- und Objektliterale und vermeiden Sie die Verwendung von Konstruktoren Array(), Object()

 /**Nicht empfohlen**/
var a = neues Array();
a[0] = 1;
a[1] = "hallo";
a[2] = 45;
var o = neues Objekt();
o.name = "Rechnung";
o.Alter = 13;
/**fördern**/
var a = [1, "hallo", 45];
var o = {
    Name: "Rechnung",
    Alter: 13
};

Typkonvertierung

1. Wandeln Sie die Zahl in eine Zeichenfolge um.

Anwendung "" +1, die Effizienz ist am höchsten.

In Bezug auf die Leistung: ""+string>String()>.toString()>new String().

 String() ist eine interne Funktion und daher sehr schnell.
.toString() muss die Funktion im Prototyp abfragen, daher ist es etwas langsamer.
new String() ist am langsamsten.

2. Wandeln Sie Gleitkommazahlen in Ganzzahlen um.

Falsche Verwendung von parseInt().

parseInt() wird zum Umwandeln von Zeichenfolgen in Zahlen verwendet, nicht zum Umwandeln zwischen Gleitkommazahlen und Ganzzahlen.

Stattdessen sollte Math.floor() oder Math.round() verwendet werden.

Da es sich bei Math um ein internes Objekt handelt, benötigt Math.floor() für die Abfrage von Methoden und Aufrufe eigentlich nicht viel Zeit und ist am schnellsten.

Zyklus
1. Definieren Sie Variablen, um sie nicht jedes Mal abzurufen

 /**Geringe Effizienz**/   
var divs = document.getElementsByTagName("div");    
für(var i = 0; i < divs.Länge; i++){   
    ...  
}    
/**Hohe Effizienz, geeignet zum Abrufen von DOM-Sammlungen. Wenn es sich um ein reines Array handelt, gibt es kaum einen Unterschied zwischen den beiden Fällen**/  
var divs = document.getElementsByTagName("div");   
für(var i = 0, len = divs.length; i < len; i++){   
    ... 
}

2. Vermeiden Sie die Verwendung von Try-Catch in Schleifen.

Die Try-Catch-Finally-Anweisung erstellt dynamisch Variablen und fügt sie während der Ausführung der Catch-Anweisung in den aktuellen Bereich ein, was gewisse Auswirkungen auf die Leistung hat.

Wenn Sie einen Mechanismus zur Ausnahmebehandlung benötigen, können Sie ihn außerhalb der Schleife verwenden.

Verwenden von try-catch außerhalb einer Schleife

 versuchen {
  für (var i = 0; i < 200; i++) {}
} Fang (e){}

3. Vermeiden Sie das Durchlaufen einer großen Anzahl von Elementen und versuchen Sie, den Durchlaufbereich zu reduzieren.

Optimierung der Umfangskette und des Abschlusses
1. Geltungsbereich.

Der Gültigkeitsbereich ist ein wichtiger Betriebsmechanismus in der JavaScript-Programmierung und spielt eine entscheidende Rolle bei der synchronen und asynchronen Programmierung in JavaScript sowie bei der Speicherverwaltung in JavaScript. In JAVASCRIPT können die folgenden Punkte einen Bereich bilden.

 Der Funktionsaufruf mit Anweisung erstellt seinen eigenen Bereich und erhöht somit die Länge des Bereichs, in dem der Code ausgeführt wird.
Globaler Umfang.

Nehmen Sie den folgenden Code als Beispiel:

 var foo = Funktion() {
  var lokal = {};
};
foo();
console.log(lokal); //=> undefiniert

var bar = Funktion() {
  lokal = {};
};
Bar();
console.log(lokal); //=> {}

/**Hier definieren wir die Funktion foo() und die Funktion bar(), die beide eine Variable namens „local“ definieren sollen. In der Funktion foo() verwenden wir die var-Anweisung, um eine lokale Variable zu deklarieren, und da innerhalb des Funktionskörpers ein Bereich gebildet wird, wird diese Variable in diesem Bereich definiert. Darüber hinaus wird im Hauptteil der Funktion foo() keine Bereichserweiterung durchgeführt, sodass nach Ausführung der Funktion auch die lokale Variable zerstört wird. Auf die Variable kann im äußeren Bereich nicht zugegriffen werden. In der Funktion bar() werden lokale Variablen nicht mit der Anweisung var deklariert. Stattdessen wird local direkt als globale Variable definiert. Daher kann der äußere Bereich auf diese Variable zugreifen. **/

lokal = {};
// Die Definition hier ist äquivalent zu global.local = {};

2. Geltungsbereichskette

Bei der JAVASCRIPT-Programmierung stoßen Sie auf Szenarien mit mehreren Ebenen verschachtelter Funktionen. Dies ist eine typische Darstellung der Bereichskette.

 Funktion foo() {
  var val = "hallo";
  Funktion bar() {
    Funktion baz() {
      global.val = "Welt;"
    };
    baz();
    console.log(val); //=> hallo
  };
  Bar();
};
foo();

/**In ‚JAVASCRIPT‘ werden Variablenbezeichner vom aktuellen Bereich nach außen bis zum globalen Bereich durchsucht. Der Zugriff auf Variablen im JAVASCRIPT-Code kann daher nur nach außen erfolgen, nicht umgekehrt. Die Ausführung der Funktion baz() definiert eine globale Variable val im globalen Gültigkeitsbereich. In der Funktion bar() gilt beim Zugriff auf den Bezeichner val das Suchprinzip von innen nach außen: Wird er im Gültigkeitsbereich der Funktion bar nicht gefunden, wird in der oberen Ebene, also im Gültigkeitsbereich der Funktion foo(), danach gesucht. Der Schlüssel zu aller Verwirrung liegt jedoch hier: Dieser Bezeichnerzugriff findet eine passende Variable im Gültigkeitsbereich der Funktion foo() und sucht nicht weiter außerhalb, sodass die in der Funktion baz() definierte globale Variable val keinen Einfluss auf diesen Variablenzugriff hat. **/

3. Reduzieren Sie die Anzahl der Suchvorgänge in der Bereichskette

 /**Geringe Effizienz**/
für(var i = 0; i < 10000; i++){
    var but1 = document.getElementById("but1");
}
/**Hohe Effizienz**/
/**Globale Suche vermeiden**/
var doc = Dokument;
für(var i = 0; i < 10000; i++){
    var but1 = doc.getElementById("but1");
}
/**Im obigen Code besteht der zweite Fall darin, zuerst die Variable des globalen Objekts in der Funktion zu speichern und dann direkt auf die Variable zuzugreifen, während der erste Fall darin besteht, die Bereichskette jedes Mal bis zur globalen Umgebung zu durchlaufen. Wir können sehen, dass der zweite Fall tatsächlich nur einmal durchlaufen wird, während der erste Fall jedes Mal durchlaufen wird, und dieser Unterschied wird bei mehrstufigen Bereichsketten und mehreren globalen Variablen sehr deutlich. Die Anzahl der Suchvorgänge in der Bereichskette beträgt O(n). Indem wir eine lokale Variable erstellen, die auf „Dokument“ verweist, können wir die Leistung dieser Funktion verbessern, indem wir die Suche auf eine globale beschränken. **/

4. Abschluss

Die Kennungssuche in JAVASCRIPT erfolgt nach dem Prinzip „von innen nach außen“.

 Funktion foo() {
  var local = "Hallo";
  return Funktion() {
    Rückgabe vor Ort;
  };
}
var bar = foo();
console.log(bar()); //=> Hallo

/**Die hier gezeigte Technik, um dem äußeren Bereich Zugriff auf den inneren Bereich zu ermöglichen, wird als Schließung bezeichnet. Durch die Anwendung höherwertiger Funktionen wird der Gültigkeitsbereich der Funktion foo() „erweitert“. Die Funktion foo() gibt eine anonyme Funktion zurück, die im Gültigkeitsbereich der Funktion foo() existiert, sodass sie auf die lokalen Variablen im Gültigkeitsbereich der Funktion foo() zugreifen und ihre Referenzen speichern kann. Da diese Funktion die lokale Variable direkt zurückgibt, kann die Funktion bar() direkt im äußeren Bereich ausgeführt werden, um die lokale Variable zu erhalten. **/

Closure ist eine erweiterte Funktion von JAVASCRIPT. Da es die Funktion mit internen Variablenreferenzen aus der Funktion herausnimmt, werden die Variablen im Gültigkeitsbereich nach Ausführung der Funktion nicht unbedingt zerstört, bis alle Referenzen auf die internen Variablen freigegeben sind. Daher kann die Anwendung von Closures leicht dazu führen, dass Speicher nicht freigegeben wird.

Gutes Verschlussmanagement.

Wenn Sie Closures für die Schleifenereignisbindung, private Eigenschaften, Rückrufe mit Parametern usw. verwenden müssen, gehen Sie mit den Details sorgfältig um.

 Schleifenbindungsereignisse, wir gehen von einem Szenario aus: Es gibt sechs Schaltflächen, die sechs Ereignissen entsprechen. Wenn der Benutzer auf die Schaltfläche klickt, wird das entsprechende Ereignis an der angegebenen Stelle ausgegeben.

var btns = document.querySelectorAll('.btn'); // 6 Elemente
var Ausgabe = document.querySelector('#Ausgabe');
var Ereignisse = [1, 2, 3, 4, 5, 6];
// Fall 1
für (var i = 0; i < btns.Länge; i++) {
  btns[i].onclick = Funktion(evt) {
    output.innerText += 'Geklickt ' + events[i];
  };
}
/**Die erste Lösung hier ist offensichtlich ein typischer Fehler bei einem Schleifenbindungsereignis. Ich werde hier nicht ins Detail gehen. Weitere Einzelheiten finden Sie in meiner Antwort an einen Internetnutzer. Der Unterschied zwischen der zweiten und dritten Lösung liegt in den Parametern, die vom Abschluss übergeben werden. **/
// Fall 2
für (var i = 0; i < btns.Länge; i++) {
  btns[i].onclick = (Funktion(Index) {
    Rückgabefunktion (evt) {
      output.innerText += 'Geklickt ' + events[index];
    };
  })(ich);
}
/**Die zweite Lösung übergibt den aktuellen Schleifenindex als Parameter, während die letztere direkt das entsprechende Ereignisobjekt übergibt. Letzteres ist eigentlich besser für groß angelegte Datenanwendungen geeignet. Da in der funktionalen Programmierung von JavaScript die beim Aufruf einer Funktion übergebenen Parameter Objekte vom Basistyp sind, ist der im Funktionskörper erhaltene formale Parameter ein kopierter Wert, sodass dieser Wert als lokale Variable im Gültigkeitsbereich des Funktionskörpers definiert wird. Nach Abschluss der Ereignisbindung kann die Ereignisvariable manuell dereferenziert werden, um den Speicherverbrauch im äußeren Gültigkeitsbereich zu reduzieren. Darüber hinaus werden beim Löschen eines Elements auch die entsprechende Ereignisüberwachungsfunktion, das Ereignisobjekt und die Abschlussfunktion zerstört und wiederverwendet. **/
//Fall 3
für (var i = 0; i < btns.Länge; i++) {
  btns[i].onclick = (Funktion(Ereignis) {
    Rückgabefunktion (evt) {
      output.innerText += 'Geklickt ' + Ereignis;
    };
  })(Ereignisse[i]);
}

Vermeidung der Schließungsfalle

Closures sind ein mächtiges Werkzeug, sie sind aber auch eine der Hauptursachen für Performanceprobleme. Die unsachgemäße Verwendung von Closures kann zu Speicherlecks führen.

Die Leistung von Closures ist nicht so gut wie bei der Verwendung interner Methoden und sogar schlechter als bei der Wiederverwendung externer Methoden.

Da die DOM-Knoten des IE 9-Browsers als COM-Objekte implementiert sind, erfolgt die COM-Speicherverwaltung durch Referenzzählung. Ein Problem bei der Referenzzählung sind Zirkelverweise. Sobald das DOM auf einen Abschluss (z. B. einen Ereignishandler) verweist und die übergeordneten Elemente des Abschlusses auf das DOM verweisen, entsteht ein Zirkelverweis, der zu Speicherlecks führt.

Funktionen sinnvoll nutzen

Verwenden Sie eine anonyme Funktion, um den Code auf der äußersten Ebene zu umschließen.

 ;(function() { // Hauptgeschäftscode})();

Einige sind sogar noch fortgeschrittener:

 ;(Funktion(win, doc, $, undefiniert) {
  // Hauptgeschäftscode})(window, document, jQuery);

Sogar modulare Front-End-Ladelösungen wie RequireJS, SeaJS, OzJS usw. nehmen eine ähnliche Form an:

 /**ErforderlichJS**/
definieren(['jquery'], Funktion($) {
  // Hauptgeschäftscode});
/**SeaJS**/
definieren('Modell', ['dep', 'Unterstrich'], Funktion($, _) {
  // Hauptgeschäftscode});

Machen Sie sinnvollen Gebrauch von Rückruffunktionen. <br />Beim Erstellen von Webseiten kapseln wir normalerweise die häufig verwendeten Stellen in Funktionen. Machen Sie beim Kapseln von Funktionen sinnvollen Gebrauch von Rückruffunktionen.

Hier sind einige Beispiele:

 Funktion getData(Rückruf){
    $.ajax({
        URL: "",
        Daten:{},
        Datentyp: „json“,
        Typ: „get“,
        Erfolg:Funktion(Daten){
            Rückruf(null,Daten)
        }
    })

}

Wenn wir es aufrufen, können wir Folgendes tun:

 getData(Funktion(Fehler,Daten){
 console.log(Daten)
})

Der schnellste Weg zum Einfügen von Elementen in ein Array <br />Das Einfügen von Elementen in ein Array ist eine sehr häufige Aufgabe. Sie können „Push“ verwenden, um Elemente am Ende eines Arrays einzufügen, „Unshift“, um Elemente am Anfang eines Arrays einzufügen, oder „Splice“, um Elemente in der Mitte eines Arrays einzufügen. Diese bekannten Methoden bedeuten jedoch nicht, dass es keine effizienteren Methoden gibt.

Element am Ende einfügen

Wir haben 2 Arrays

 var arr = [1,2,3,4,5];
var arr2 = [];

Der Test läuft wie folgt ab:

 arr[arr.length] = 6; // am schnellsten arr.push(6); // 34,66 % langsamer
arr2 = arr.concat([6]); // 85,79% langsamer

Element einfügen vor

 var arr = [1,2,3,4,5];
arr.unshift(0); 
[0].concat(arr);

Entdecken:

 [0].concat(arr); // Schneller arr.unshift(0); // 64,70 % Langsamer

Fügen Sie der Mitte eines Arrays ein Element hinzu

Mit Splice können Sie Elemente einfach in die Mitte eines Arrays einfügen, was zugleich die effizienteste Methode ist.

 var items = ['eins', 'zwei', 'drei', 'vier'];
items.splice(items.length / 2, 0, 'hallo');

<<:  Verwenden Sie vue2+elementui für Hover-Prompts

>>:  Wie gut kennen Sie sich mit reinen HTML-Tags aus?

Artikel empfehlen

Ändern Sie das JVM-Kodierungsproblem, wenn Tomcat ausgeführt wird

Frage: Vor kurzem traten bei der Bereitstellung d...

So legen Sie einen Alias ​​für einen benutzerdefinierten Pfad in Vue fest

So konfigurieren Sie benutzerdefinierte Pfadalias...

Erste Schritte mit SELinux

Bereits zu Kernel 2.6-Zeiten wurde ein neues Sich...

So installieren Sie MySQL 8.0 und melden sich bei MySQL unter MacOS an

Folgen Sie dem offiziellen Tutorial, laden Sie da...

Analyse der Docker-Methode zum Erstellen lokaler Images

Der sogenannte Container erstellt tatsächlich ein...

Zwei Möglichkeiten zum Erstellen eines privaten GitLab mit Docker

Die erste Methode: Docker-Installation 1. Ziehen ...

So schreiben Sie den Stil einer CSS3-Tianzi-Rasterliste

In vielen Projekten ist es notwendig, die Funktio...

Aktualisierungen für React Router V6

Inhaltsverzeichnis ReactRouterV6-Änderungen 1. &l...

So verwenden Sie webSocket zum Aktualisieren des Echtzeitwetters in Vue

Inhaltsverzeichnis Vorwort Informationen zu WebSo...

Webdesign-TabIndex-Element

TabIndex dient zum Drücken der Tabulatortaste, um ...

So führen Sie Linux-Befehle im Hintergrund aus

Wenn Sie einen Befehl im Terminal ausführen, müss...