2013-04-16 19 views
6

Czy ktoś mógłby wyjaśnić, dlaczego delegate wydaje się szybszy niż alias binding lub on().jest delegatem najszybszy sposób wiązania?

Jest to przypadek testowy:

jsPerf

$('p').on('click',$.noop); //80% slower 

$('p').click($.noop); //84% slower 

$(document).delegate("p", "click",$.noop); //fastest 

Sprawdzanie źródła jquery wydaje się, że przed każdym razie wiążące czek jquery dla delegatów.

Czy to jest poprawne stwierdzenie, czy jest coś jeszcze?

+2

Spróbuj ustawić 'delegate' na coś, co musisz sprawdzić. – Musa

+0

Ponieważ 'delegate()' wywołuje 'on()' (są one równoważne, z wyjątkiem kolejności argumentów), nie ma możliwości, aby był bardziej wydajny. – Barmar

+1

Zauważ, że problem nie polega na szukaniu elementów 'p': http://jsperf.com/test-on-click-delegate/2 –

Odpowiedz

6

Błąd dokonane było myśleć, że był tylko jeden element p.

Dodałem kolejny test z tylko console.log($('p').length); i pokazałem, że z testu było 7 p, którego widoczność oczywiście nie była ograniczona do HTMLa, który zbudowałeś w kodzie przygotowania.

Oznacza to, że dwie pierwsze funkcje musiały wykonać jeszcze 7 wiązań.

+0

To wyjaśnia wszystko, sprytne myślenie, dziękuję panu! –

5

Zarówno delegate() i bind() po prostu zadzwoń pod numer on(). Oto fragment ze źródła jQuery 1.9.0:

bind: function(types, data, fn) { 
    return this.on(types, null, data, fn); 
}, 
delegate: function(selector, types, data, fn) { 
    return this.on(types, selector, data, fn); 
}, 

Więc on() powinna być nieznacznie szybciej niż w pozostałych dwóch funkcji, ponieważ jest to jeden mniej wywołanie funkcji. Faktyczne wywołanie programu obsługi powinno być identyczne, niezależnie od tego, w jaki sposób zostało powiązane.

Ale upewnij się, że porównujesz jabłka z jabłkami. Jeśli podasz argument selector do delegate lub bind, wywołanie procedury obsługi będzie wolniejsze, ponieważ musi sprawdzić, czy cel spełnia selektor.

Powodem dla benchmarku rezultat dlatego

$("p").on('click',$.noop); 

jest równoznaczne z czymś takim:

$("p").each(function() { 
    $(this).on('click', $.noop); 
}); 

Stało się znaleźć wszystkie elementy pasujące i powiązać obsługi do nich. Wywołanie delegate() musi jedynie powiązać program obsługi z jednym elementem (dokumentem); zamiast znaleźć wszystkie elementy na wiążącą czasie, w chwili zdarzenia występuje on robi coś takiego:

if ($(event.target).is("p")) { ... } 

Zastosowanie on() to odpowiednik delegate() byłoby:

$(document).on('click', 'p', $.noop); 

Kiedy delegować od duży element, taki jak document, za każdym razem, gdy klikasz w dokumencie, wywołujesz procedurę obsługi wewnętrznej, marnując czas na testowanie, jeśli masz ponad p. Dlatego powinieneś spróbować ograniczyć zakres elementu używanego w delegate do najmniejszego elementu statycznego zawierającego wszystkie elementy dynamiczne, które chcesz przekazać.

+1

Czy mówisz, że benchmark jest nieprawidłowy? –

+0

Thx dla wyjaśnienia. Po odpowiedzi na dystroy, rozumiem to teraz. –

5

delegat jest tylko szybciej, ponieważ nie trzeba zajrzeć do żadnych elementów, jeśli używasz selektora zamiast elementów delegat będzie najwolniejszy

<div> 
<p>test</p> 
</div> 


$('p').on('click',$.noop); 
$('p').click($.noop); 
$('div').delegate("p", "click",$.noop); 

http://jsperf.com/test-on-click-delegate/3

+0

To naprawdę dobry punkt! –

Powiązane problemy