Hvordan jQuery Beginners kan teste og forbedre deres kode

jQuerys ankomst har gjort prosessen med å skrive JavaScript skremmende enkelt. Men du vil legge merke til at små endringer i koden din forbedrer lesbarheten og / eller ytelsen betydelig. Her er noen tips for å få deg på vei til å optimalisere koden din.


Sette opp plattformen

Vi trenger en solid plattform for å gjennomføre testene våre. Her er HTML-oppslaget på testsiden der vi skal kjøre alle våre tester:

     Testing av ytelsesforbedringer - Siddharth / NetTuts+   

Noen tekst her

  • Åh, hei der!

Det er ikke noe spesielt her; bare en mengde elementer som vi kan målrette og teste. Vi bruker Firebug for å logge tiden her. profil starter prosessen, og profileEnd stopper det, og legger merke til hvor mye tid oppgaven tok. Jeg bruker vanligvis Firebugs hovedprofilmetode, men for våre utfordrende formål vil dette være tilstrekkelig.


1. Oppdag om et element eksisterer

Som det er tilfelle, serverer du en enkelt skriptfil som inneholder koden din til alle sidene på nettstedet ditt. Dette er vanligvis kode som ofte utfører handlinger på ikke-eksisterende elementer i gjeldende side. Selv om jQuery håndterer problemer som disse ganske grasiøst, betyr det ikke at du bare kan overse noen problemer. Faktisk, hvis du ringer jQuerys metoder på en tom samling, vil de ikke bli kjørt.

Som en best practice, bare kjør kode som er aktuell for siden som er lastet inn, i stedet for å kaste all koden din i en enkelt dokument klar sjekk og vise den til klienten.

La oss se på det første scenariet:

 console.profile (); var ele = $ ("# somethingThatisNotHere"); ele.text ("Noen tekst"). slideUp (300) .addClass ("redigering"); $ ( "# MainItem"); console.profileEnd (); // Noen mer kjempebra, jordskjelvende kode her ._.

Firebug spytter ut følgende resultat:

Denne gangen, la oss sjekke om elementet vi ser for å utføre handlinger, eksisterer før det gjøres.

 console.profile (); var ele = $ ("# somethingThatisNotHere"); hvis (ele [0]) ele.text ("Some text"). slideUp (300) .addClass ("redigering");  $ ("# mainItem"); console.profileEnd (); // Noen mer kjempebra, jordskjelvende kode her ._. 

Og resultatene:

Se? Det er ganske enkelt, til det punktet og får jobben gjort. Merk at du ikke trenger å sjekke om et element eksisterer for hver eneste bit av koden din. Du vil legge merke til at visse større deler generelt vil ha nytte av denne metoden. Bruk dommen din her.


2. Bruk velgeren effektivt

Prøv å bruke en ID i stedet for å bestå en klasse.

Dette er et stort emne, så jeg vil holde det så kortfattet som mulig. Først må du prøve å bruke en ID i stedet for å passere en klasse, når du passerer i selektorer. jQuery bruker direkte innfødte getElementById metode for å finne et element av ID mens i tilfelle av en klasse det må gjøre noen intern voodoo for å skaffe den, i alle fall i eldre nettlesere.

Vi ser på de forskjellige valgene du kan bruke til å målrette den andre li element. Vi tester hver enkelt av dem og hvordan de endrer ytelsen.

Den første metoden, det enkleste, vil være å tydelig målrette den ved hjelp av valgt klasse. La oss se hva Firebugs profiler returnerer.

 console.profile (); $ ( "Valgt."); console.profileEnd (); 

Og resultatet: 0,308ms. Deretter prefikserer vi et tagnavn for å begrense det. På denne måten kan vi begrense søket vårt ved først å målrette de valgte DOM-elementene, med document.getElementsByTagName.

 console.profile (); $ ( "Li.selected"); console.profileEnd (); 

Og resultatet: 0.291ms. Rundt 0,02 ms barbert av. Dette er ubetydelig på grunn av det faktum at vi tester i Firefox; Det bør imidlertid bemerkes at dette ytelsesforhøyelsen vil bli vesentlig høyere i eldre nettlesere, som for eksempel Internet Explorer 6.

Deretter kommer vi ned fra ID-en til foreldreelementet.

 console.profile (); $ ("# someList .selected"); console.profileEnd (); 

Og resultatet: 0.283ms. La oss prøve å være litt mer spesifikk. Vi spesifiserer også typen av element i tillegg til forfaderens ID.

 console.profile (); $ ("# someList li.selected"); console.profileEnd (); 

Og resultatet: 0,275 ms. En annen liten del barbert av. Til slutt, la oss bare målrette det direkte ved hjelp av en ID til.

 console.profile (); $ ( "# MainItem"); console.profileEnd (); 

Og resultatet: 0.165ms. Imponerende! Dette viser deg virkelig hvor mye raskere det er å kjøre innfødte metoder. Merk at mens moderne nettlesere kan dra nytte av ting som getElementsByClassName, kan eldre nettlesere ikke - noe som resulterer i mye tregere ytelse. Overvei alltid dette når du koder.


3. Redegjøre for Sizzles Parsing-modell og legge til omfang

Sizzle, selektormotoren som jQuery bruker - bygget av John Resig - analyserer selektorer fra høyre til venstre, noe som gir noen uventede ukjente kjeder av parsing.

Vurder denne velgeren:

 $ ("# someList .selected"); 

Når Sizzle møter en slik väljare, bygger den først DOM-strukturen ved å bruke väljeren som roten, kasserer elementer som ikke har den nødvendige klassen, og for hvert element med klassen kontrollerer det om foreldrene har en ID someList.

For å ta hensyn til dette, må du sørge for at størstedelen av selgeren din er så spesifikk som mulig. For eksempel ved å spesifisere li.selected i stedet for .valgt, du kutter ned antall noder det må sjekke. Dette er grunnen til at ytelsen hoppet i forrige del. Ved å legge til flere begrensninger, reduserer du effektivt antall noder det må sjekke.

For bedre å finjustere måten elementene blir oppnådd, bør du se nærmere på å legge til en kontekst for hver forespørsel.

 var someList = $ ('# someList') [0]; $ (".valgt", noenListe);

Ved å legge til en kontekst, endrer måten elementet er søkt på. Nå er elementet som gir konteksten - someList i vårt tilfelle - blir først søkt etter, og når det er oppnådd, fjernes barnelementer som ikke har den nødvendige klassen.

Vær oppmerksom på at det generelt er en god praksis å sende et DOM-element som konteksten til jQuery-väljeren din. Bruke en kontekst er mest nyttig når den er lagret i noen variabel. Ellers kan du strømlinjeforme prosessen og bruke find () - som jQuery, selv, gjør under hetten.

 $ ( '# SomeList') finne ( 'valgt..');

Jeg vil gjerne si at resultatforhøyelsen vil bli klart definert, men jeg kan ikke. Jeg har kjørt tester på en rekke nettlesere, og om scoped-tilgangsresultatet slår det av vaniljeversjonen, avhenger av en rekke faktorer, blant annet om nettleseren støtter bestemte metoder.


4. Unngå Søkeavfall

Når du surfer gjennom andres kode, finner du ofte.

 // Andre kode $ (element) .doSomething (); // Mer kode $ (element) .doSomethingElse (); // enda mer kode $ (element) .doMoreofSomethingElse (); 

Vennligst ikke gjør dette. Noensinne. Utvikleren er instantiating dette "elementet" igjen og igjen. Dette er sløsing.

La oss se hvor mye tid en slik fryktelig kode tar for å løpe.

 console.profile (); $ ( "# MainItem") skjule (.); $ ( "# MainItem") val ( "Hello."); $ ("# mainItem"). html ("Oh, hei der!"); $ ( "# MainItem") viser (.); console.profileEnd (); 

Hvis koden er strukturert som ovenfor, kan den ene etter den andre bruke kjetting slik:

 console.profile (); $ ("# mainItem"). Skjul () .val ("Hei"). html ("Oh, hei der!"). show (); console.profileEnd ();

Ved kjetting blir elementet som først ble passert inn ervervet, og en referanse sendes videre til hver etterfølgende samtale kutte ned på kjøretid. Ellers opprettes et nytt jQuery-objekt hver gang.

Men hvis i motsetning til ovenfor, delene som refererer til elementet ikke er samtidige, må du cache elementet og deretter gjøre alle de samme operasjonene som før.

 console.profile (); var elem = $ ("# mainItem"); elem.hide (); // Noen kode elem.val ("Hei"); // Mer kode elem.html ("Åh, hei der!"); // enda mer kode elem.show (); console.profileEnd (); 

Som det fremgår av resultatene, reduserer caching eller kjetting betydelig kjøringen.


5. Utfør DOM Manipulation mer intelligent

Å foreslå ikke-tradisjonell DOM-manipulasjon i min tidligere artikkel trakk litt flak fra noen få personer før det ble vist at ytelsesforhøyelsen virkelig er verdt det. Vi skal nå teste det selv.

For testen oppretter vi 50 li elementer, og legg dem til den nåværende listen, og avgjøre hvor mye tid det tar.

Vi vurderer den vanlige, ineffektive metoden først. Vi legger i hovedsak elementet til listen hver gang løkken løper.

 console.profile (); var list = $ ("# someList"); for (var i = 0; i<50; i++)  list.append('
  • Vare # '+ i +'
  • '); console.profileEnd ();

    La oss se hvordan det gjorde, skal vi?

    Nå følger vi en litt annen vei. Vi legger i hovedsak den nødvendige HTML-strengen til en variabel firs, og bare reflow DOM en gang.

     console.profile (); var list = $ ("# someList"); var elementer = ""; for (var i = 0; i<50; i++) items += '
  • Vare # '+ i +'
  • '; list.append (elementer); console.profileEnd ();

    Som forventet har tiden tatt redusert betydelig.

    Hvis du bruker jQuery som en erstatning for getElementById, men aldri utnytter noen av de angitte metodene, gjør du det feil.

    Hvis du ønsker å ta ting videre, spør deg selv om du virkelig trenger å opprette et nytt jQuery-objekt alt for å målrette mot noe element? Hvis du bruker jQuery som en erstatning for document.getElementById, men aldri utnytte noen av de angitte metodene, gjør du det feil. I dette tilfellet kan vi komme unna med rå JS.

     console.profile (); var list = document.getElementById ('someList'); var items = "; for (var i = 0; jeg<50; i++) items += '
  • Vare # '+ i +'
  • '; list.innerHTML = elementer; console.profileEnd ();

    Noen advarsler

    Du vil merke at forskjellen i kjøretid mellom optimalisert og uoptimalisert kode er i brøkdel av et millisekundsområde. Dette skyldes at vårt testdokument er svært lite med et umulig lite antall noder. Når du begynner å jobbe med produksjonsnivåer med noen få tusen noder i den, vil det virkelig legge opp.

    Vær også oppmerksom på at i de fleste av disse testene er jeg bare å få tilgang til elementene. Når du begynner å bruke riktige funksjoner til dem, vil deltaet i kjøretiden øke.

    Jeg forstår også at dette ikke er den mest vitenskapelige metoden for å teste ytelsen, men for å få en generell følelse av hvor mye hver av disse endringene påvirker ytelsen, synes jeg dette er tilstrekkelig tilstrekkelig.

    Til slutt, i de fleste av dine webapps, vil forbindelseshastigheten og responstiden til den aktuelle webserveren spille en større rolle i ytelsen til appen din, mer enn tweaksene i koden du vil lage. Likevel er dette fortsatt viktig informasjon, og vil hjelpe deg nedover linjen når du prøver å eke ut så mye ytelse som mulig fra koden din.


    Det var alt folkens

    Og vi er ferdige. Noen få poeng å huske på når du prøver å optimalisere koden din; Dette er ikke den altomfattende listen over tweaks, selvfølgelig, og punktene kan ikke nødvendigvis gjelde for alle situasjoner. Uansett, jeg ser nøye på kommentarene for å lese hva du har å si om emnet. Enhver feil du ser her? Slett meg en linje under.

    Spørsmål? Hyggelige ting å si? Kritikk? Treff kommentar delen og la meg en kommentar. Glad koding!