1

Recently I've been working on a relatively simple personal project where I need to generate quite a fair amount of Javascript to bind various event handlers to elements (such as on('click')) and it got me wondering about the efficiency of generating multiple on('click') definitions per element, based on the values in the array (which could change per page load), or having a single function that binds it to every element. For example:

PHP generating jQuery

<?php
foreach($var as $key => $val){
    echo '$("' . $key . '").on("click", function(){
        // do something
    });';
}
// Which will generate:
// $(elemkey1).on("click", function(){ // do something });
// $(elemkey2).on("click", function(){ // do something });
// $(elemkey3).on("click", function(){ // do something });
// $(elemkey4).on("click", function(){ // do something });
// ...

Pure jQuery

$(elem).each(function(){
    // do something
);

So my question is: Which would be the most efficient way of declaring something like the above?

Obviously the second example is dependant on the selector used (whether it's an id or class for example and I'm fully aware of the caveats here) but that aside, assuming the right selectors are used, I'm curious to know if there's a slight performance benefit in declaring event handlers per element explicitly using a PHP for loop as opposed to the jQuery .each() or similar method.

ScottMcGready
  • 1,612
  • 2
  • 24
  • 33
  • 1
    @MattS happy to concede if the consensus is that it's a duplicate but I feel this is different as it doesn't need to necessarily be a click event (although appreciate that opens the question to be extremely broad). Also I'm interested in any caveats that would mean generating jQuery/JS via PHP (or other dynamic language) that would impact on performance. Still, happy either way. – ScottMcGready Jan 25 '18 at 22:15

2 Answers2

5

One selector is preferred

There is a performance difference, and once you break the 3000 or so element size it should become visible. At 10,000 it is undeniable.

It is vastly more efficient to use a single selector one time in order to handle the event as that way the click event only needs to be checked once when triggered.

Event dispatch is the primary reason

The main reason for the change in efficiency is the way events work. When an event is dispatched, it must propagate all the way down to the element through the DOM to the target, and then bubble all the way back up. This is highly inefficient compared to having the event triggered further up in the DOM.

Please read 3.1. Event dispatch and DOM event flow at the W3C for some of the finer grain details.

Here is one of their diagrams from that section:

Bandwidth and caching can also be problematic in the php-generated scenario

Aside from the JavaScript execution angle, there is also the issue of the php generated code. While it may be negligible for a small set, it is problematic from a bandwidth perspective for larger sets (this comes into play more significantly when dealing with mobile browsing). Moreover, as the server is generating the javascript code, it will be very difficult to cache for the browser assuming that the sets will often be different therefore generating different selectors. A pitfall would also be that without a cache breaking scheme for the selector sets (perhaps making use of the terms used to generate them) then the wrong set of selectors could be cached.

Travis J
  • 81,153
  • 41
  • 202
  • 273
1

[Is] there a slight performance benefit in declaring event handlers per element explicitly using a PHP for loop as opposed to the jQuery .each() or similar method?

In the absence of event delegation, the echo loop in PHP code has two additional overheads:

  1. bandwidth (the served page size is larger)
  2. The echo loop creates a separate anonymous function client side for each element it is assigned to:

    $(elemkey1).on("click", function(){ // do something });
    $(elemkey2).on("click", function(){ // do something });
    $(elemkey3).on("click", function(){ // do something });
    $(elemkey4).on("click", function(){ // do something });
    

    would create four separate function objects to handle clicks.

Client side assignment in JQuery only creates one handler function object, when evaluating the call parameter expression in the statement:

$(elem).each(function(){
    // do something
);

If the number of elements is huge, event delegation by capturing the event on a parent node higher in the DOM, and checking which element was the target of the (click) event is preferable. From comments, this question on best practice goes into further detail.

In light of @TravisJ 's answer, it would appear that event capturing may increase client responsiveness in supported browsers. The idea is to be notified of the event during the capturing phase and stop it propagating further if processed by the click handler.

traktor
  • 17,588
  • 4
  • 32
  • 53