jQuerys ankomst har gjort processen med att skriva JavaScript skrattsamt enkelt. Men du märker att små ändringar i din kod förbättrar läsbarheten och / eller prestanda betydligt. Här är några tips för att få dig på väg att optimera din kod.
Vi behöver en solid plattform för att utföra våra test. Här är HTML-markupen för testsidan där vi kör alla våra test:
Testa resultatförbättringar - Siddharth / NetTuts+ Några text här
- Åh hej där!
Det finns inget speciellt här; bara en massa element som vi kan rikta och testa. Vi använder Firebug för att logga tiderna här. profil börjar processen, och profileEnd stoppar det och noterar hur mycket tid uppgiften tog. Jag brukar använda Firebugs huvudprofilmetod, men för våra utmanande ändamål kommer det att vara tillräckligt.
Som det är fallet kommer du att betjäna en enda skriptfil som innehåller din kod till alla sidor på din webbplats. Detta är vanligtvis kod som ofta utför åtgärder på obefintliga element på den aktuella sidan. Även om jQuery hanterar problem som dessa ganska graciöst betyder det inte att du bara kan ignorera några problem. Om du ringer jQuerys metoder på en tom samling, kommer de inte att köras.
Som bästa praxis kör du bara koden som är tillämplig på den för närvarande laddade sidan, istället för att kasta hela din kod till en enkel dokumentkontroll och serverar den för kunden.
Låt oss titta på det första scenariot:
console.profile (); var ele = $ ("# somethingThatisNotHere"); ele.text ("En del text"). slideUp (300) .addClass ("redigering"); $ ( "# MainItem"); console.profileEnd (); // Några mer fantastiska, slipade koden här..
Firebug spetsar ut följande resultat:
Den här gången, låt oss kolla om det element vi letar efter att utföra handlingar finns före det.
console.profile (); var ele = $ ("# somethingThatisNotHere"); om (ele [0]) ele.text ("Some Text"). slideUp (300) .addClass ("redigering"); $ ("# mainItem"); console.profileEnd (); // Några mer fantastiska, slipade koden här..
Och resultaten:
Se? Det är ganska enkelt, till den punkten och får jobbet gjort. Observera att du inte behöver kontrollera om ett element finns för varje bit av din kod. Du märker på din sida att vissa större delar generellt kommer att dra nytta av denna metod. Använd din dom här.
Försök att använda ett ID istället för att gå i klass.
Detta är ett stort ämne så jag kommer att hålla den så koncis som möjligt. Först försöker du använda ett ID istället för att passera en klass när du passerar i väljare. jQuery använder direkt den inhemska getElementById metod för att hitta ett element med ID medan i fallet med en klass måste det göra vissa interna voodoo för att förvärva det, åtminstone i äldre webbläsare.
Vi tittar på de olika selektorerna som du kan använda för att rikta sig mot andra li element. Vi ska testa var och en av dem och hur de ändrar prestandan.
Den första metoden, det enklaste, kommer att vara att tydligt rikta den med hjälp av vald klass. Låt oss se vad Firebugs profiler returnerar.
console.profile (); $ ( "Valts."); console.profileEnd ();
Och resultatet: 0.308ms. Därefter prefixar vi ett tagnamn för att begränsa det. På så sätt kan vi begränsa vår sökning genom att först rikta in de utvalda DOM-elementen, med document.getElementsByTagName.
console.profile (); $ ( "Li.selected"); console.profileEnd ();
Och resultatet: 0.291ms. Grovt 0,02 ms rakas bort. Detta är försumbar på grund av det faktum att vi testar i Firefox; Det bör emellertid noteras att denna prestationsökning kommer att bli betydligt högre i äldre webbläsare, som Internet Explorer 6.
Därefter kommer vi ned från stamelementets ID.
console.profile (); $ ("# someList .selected"); console.profileEnd ();
Och resultatet: 0,233ms. Låt oss försöka vara lite mer specifika. Vi anger också typen av element utöver förfaderens ID.
console.profile (); $ ("# someList li.selected"); console.profileEnd ();
Och resultatet: 0,275 ms. En annan liten del rakade bort. Slutligen, låt oss bara rikta in det direkt med ett ID till.
console.profile (); $ ( "# MainItem"); console.profileEnd ();
Och resultatet: 0.165ms. Imponerande! Det här visar verkligen hur mycket snabbare det är att köra inbyggda metoder. Observera att medan moderna webbläsare kan dra nytta av saker som getElementsByClassName, kan äldre webbläsare inte - vilket resulterar i mycket långsammare prestanda. Överväga alltid detta när du kodar.
Sizzle, den väljarmotor som jQuery använder - byggd av John Resig - analyserar väljare från höger till vänster, vilket ger upphov till några oväntade parsingskedjor.
Tänk på den här väljaren:
$ ("# someList .selected");
När Sizzle möter en sådan väljare, bygger den först DOM-strukturen med väljaren som root, kasserar objekt som inte har den obligatoriska klassen och för varje element med klassen kontrollerar den om dess förälder har ett ID-nummer someList.
För att ta hänsyn till detta, se till att den högsta delen av din väljare är så specifik som möjligt. Till exempel genom att ange li.selected istället för .vald, du skär ner antalet noder det måste kontrollera. Detta är anledningen till att prestanda hoppade i föregående avsnitt. Genom att lägga till ytterligare begränsningar reducerar du effektivt antalet noder det måste kontrollera.
För att bättre finjustera hur elementen erhålls bör du titta på att lägga till ett sammanhang för varje förfrågan.
var someList = $ ('# someList') [0]; $ (". selected", someList);
Genom att lägga till ett sammanhang ändras helt hur elementet söks. Nu ger elementet sammanhanget - someList i vårt fall - är först sökt efter, och när det har erhållits, avlägsnas barnelement som inte har den nödvändiga klassen.
Observera att det i allmänhet är en bra metod att skicka ett DOM-element som kontext för din jQuery-väljare. Att använda ett sammanhang är mest användbart när det lagras i en viss variabel. Annars kan du effektivisera processen och använda find () - vilket jQuery, självt, gör under huven.
$ (# SomeList) hitta ( "valt.).
Jag skulle vilja säga att prestationsökningen kommer att definieras tydligt, men jag kan inte. Jag har kört test på ett antal webbläsare och huruvida den scopedinställningsprestandan slår den hos vaniljversionen beror på ett antal faktorer, inklusive om webbläsaren stöder specifika metoder.
När du bläddrar igenom någon annans kod hittar du ofta.
// Andra kod $ (element) .doSomething (); // Mer kod $ (element) .doSomethingElse (); // Ännu mer kod $ (element) .doMoreofSomethingElse ();
Vänligen gör inte det här. Någonsin. Utvecklaren instantiating detta "element" om och om igen. Detta är slöseri.
Låt oss se hur mycket tid en sådan hemsk kod tar att springa.
console.profile (); $ ( "# MainItem") döljer (). $ ( "# MainItem") val ( "Hello"). $ ("# mainItem"). html ("Åh, hej där!"); $ ( "# MainItem") visa (). console.profileEnd ();
Om koden är strukturerad som ovan, kan den ena efter den andra använda kedjan så här:
console.profile (); $ ("# mainItem"). hide () .val ("Hello"). html ("Åh, hej där!"). visa (); console.profileEnd ();
Genom att kedja är det initialt passerade elementet förvärvat och en referens överförs till varje efterföljande samtal som skär ner på exekveringstiden. Annars skapas ett nytt jQuery-objekt varje gång.
Men om inte de delar som refererar till elementet inte är samtidiga, måste du cache elementet och sedan göra samma operation som tidigare.
console.profile (); var elem = $ ("# mainItem"); elem.hide (); // Någon kod elem.val ("Hello"); // Mer kod elem.html ("Åh, hej där!"); // Ännu mer kod elem.show (); console.profileEnd ();
Såsom framgår av resultaten minskar kachning eller kedjering avsevärt minskning av körtiden.
Att föreslå icke-traditionell DOM-manipulation i min tidigare artikel drog en liten flak från några få människor innan det visades att prestationshöjningen verkligen är värt det. Vi ska nu testa det själva.
För testet skapar vi 50 li element och lägg till dem i den aktuella listan och bestäm hur mycket tid det tar.
Vi granskar den normala, ineffektiva metoden först. Vi lägger i grunden elementet till listan varje gång slingan körs.
console.profile (); var list = $ ("# someList"); för (var i = 0; i<50; i++) list.append('
Låt oss se hur det gjorde, ska vi?
Nu följer vi en lite annan väg. Vi lägger väsentligen ihop den nödvändiga HTML-strängen till en variabelgran, och sedan återflöder endast DOM en gång.
console.profile (); var list = $ ("# someList"); var items = ""; för (var i = 0; i<50; i++) items += '
Som förväntat har den tid som tagits minskat avsevärt.
Om du använder jQuery som ersättare för getElementById, men aldrig utnyttjar någon av dess tillhandahållna metoder, så gör du det fel.
Om du vill ta saker längre, fråga dig själv om du verkligen behöver skapa ett nytt jQuery-objekt allt för att rikta in något element? Om du använder jQuery som en ersättning för document.getElementById, men aldrig utnyttja någon av dess tillhandahållna metoder, gör du det fel. I det här fallet kan vi komma undan med rå JS.
console.profile (); var list = document.getElementById ('someList'); var items = "; för (var i = 0; i<50; i++) items += '
Du kommer märka att skillnaden i exekveringstiden mellan den optimerade och un optimerade koden ligger i bråkdelen av ett millisekunderområde. Detta beror på att vårt testdokument är mycket litet med ett omöjligt litet antal noder. När du väl börjar jobba med produktionsnivåer med några tusen noder i det, kommer det verkligen att fungera.
Observera också att i de flesta av dessa test får jag bara tillgång till elementen. När du börjar tillämpa riktiga funktioner på dem, ökar deltaet i exekveringstiden.
Jag förstår också att detta inte är den mest vetenskapliga av metoder för att testa prestanda, för att få en allmän känsla för hur mycket var och en av dessa förändringar påverkar prestanda, anser jag att detta är tillräckligt.
Slutligen, i de flesta av dina webbapps, kommer anslutningshastigheten och svarstiden för den aktuella webbservern att spela en större roll i utförandet av din app mer än tweaksna i koden du ska göra. Ändå är detta fortfarande viktig information och hjälper dig att minska linjen när du försöker att eke ut så mycket prestanda som möjligt från din kod.
Och vi är klara. Några punkter att komma ihåg när du försöker optimera din kod det här är inte hela listan över tweaks, och poängen kanske inte nödvändigtvis gäller för alla situationer. Hur som helst, jag tittar noga på kommentarerna för att läsa vad du måste säga om ämnet. Något misstag ses du här? Släpp mig en rad nedan.
Frågor? Trevliga saker att säga? Kritik? Klicka på kommentarfältet och lämna mig en kommentar. Lycklig kodning!