Som engelska talare är våra sinnen inriktade på att tolka data och text från vänster till höger. Som det visar sig är många av de moderna JavaScript-väljarmotorerna (jQuery, YUI 3, NWMatcher) och den infödda querySelectorAll
, analysera väljare strängar från höger till vänster.
Det är viktigt att notera att du oftast inte behöver oroa dig för väljarens prestanda för mycket - så länge dina väljare inte är motbjudande. jQuery sizzle är otroligt snabb och tillmötesgående.
Tänk på följande väljare:
$ ('box p');
Även om vissa - generellt äldre valmotorer först frågar DOM för elementet med a klass
av låda
, och fortsätt sedan till att hitta något p
taggar som är barn, jQuery fungerar i omvänd ordning. Det börjar med att fråga DOM för Allt stycke-taggar på sidan, och jobbar sedan upp med modernoderna och söker efter .låda
.
Vi kan använda den utmärkta webbplatsen JsPerf.com för att testa detta.
// Markeringen// Testet // 1. $ ('# box p'); // 2. $ ('# box'). Hitta ('p');Hej
Bilden ovan visar att du använder hitta()
eller barn()
är ungefär 20-30% snabbare, beroende på webbläsaren.
JQuery-biblioteket har en optimering som omedelbart avgör om en id
skickades till jQuery-objektet ( $ (# Box)
). Om så är fallet behöver den inte använda Sizzle; i stället går det snabbt väljaren till getElementById
. Och, naturligtvis, om webbläsaren är tillräckligt modern, querySelectorAll
kommer att ta över för Sizzle.
Å andra sidan med $ ('# box p')
, jQuery behöver analysera denna sträng med Sizzle API, vilket kommer att ta lite längre tid (även om Sizzle har en optimering för väljare som börjar med en id
). Det är just därför det är också marginellt snabbare att göra saker som $ ('. Elems). Först ()
över $ (Elems. Första)
. Den senare väljaren måste analyseras.
Låt oss granska ett annat exempel:
$ ('# container>: inaktiverad');
Denna väljare verkar lämplig. Hitta alla inaktiverade ingångar (eller faktiskt element) som finns inom #behållare
. Men som vi har lärt oss, jQuery och den infödda querySelectorAll
arbeta höger till vänster. Det betyder att jQuery kommer att fånga, bokstavligen, varje element i DOM, och bestämma om det är Inaktiverad
attributet är satt till true. Observera att det inte finns någon förfiltrering för att först hitta alla ingångar på sidan. I stället kommer varje element i DOM att frågas.
// Från jQuery-källan inaktiverad: funktion (elem) return elem.disabled === true;
När det är samlat en samling, reser den sedan upp kedjan till föräldern och bestämmer om det är #behållare
. Visst är detta inte effektivt, och även om det är sant att kanske för mycket uppmärksamhet i samhället betalas till väljareprestanda, borde vi fortfarande sträva efter att inte skriva överintensiva väljare när det är möjligt.
Du kan förbättra den här väljaren lite genom att göra:
// Bättre $ ('# container> inmatning: inaktiverad');
Denna kod kommer att begränsa frågan till alla inmatningar på sidan först (snarare än varje element). Ännu bättre, men vi kan återigen använda hitta
eller barn
metod.
$ (# Container) barn ( 'input: disabled');.
Det är viktigt för mig att upprepa att du ärligt inte behöver oroa dig för väljarens prestanda för mycket. Det finns många optimeringar i jQuery som hjälper dig. Det är i allmänhet bättre att fokusera på större biljettobjekt, som kodorganisation och struktur.
Som ett exempel, om Sizzle kommer över en väljare som $ ('# box p')
, Det är sant att det fungerar höger mot vänster, men det finns också en snabb regexoptimering som först bestämmer om den första delen av väljaren är en id
. Om så är fallet kommer det att använda det som sammanhang när du söker efter stycke-taggarna.
Det är dock alltid användbart att veta vad som händer bakom kulisserna - åtminstone på en mycket låg nivå.