jQuery event delegation

JavaScript performance comparison

Revision 60 of this test case created

Info

Comparing performance of adding .click() to 400 table cells vs using .on() to listen for click events bubbling up the DOM tree.

Preparation code

<div class="someDiv"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
</script>
<script>
Benchmark.prototype.setup = function() {
    $('.someDiv').html('');
};

Benchmark.prototype.teardown = function() {
    $('.someDiv').html('');
};
</script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
no delegation
var $document = $(document),
    someDiv = $('.someDiv'),
    addTable = function(){
        var table = $('<table/>').appendTo(someDiv),
            i, tr,
            j, td;
        for (i = 0; i < 20; i++) {
            tr = $('<tr/>').appendTo(table);
            for (j = 0; j < 20; j++) {
                td = $('<td/>').appendTo(tr).
                    on('click.activate', function() {
                        $(this).toggleClass('active');
                    }).
                    on('mouseenter.hover', function() {
                        $(this).addClass('hover');
                    }).
                    on('mouseleave.hover', function() {
                        $(this).removeClass('hover');
                    });
            }
        }
        return table
    };

for (var i = 0; i < 5; i++)
    addTable();
someDiv.find('td:first').click();
pending…
with delegation
var $document = $(document),
    someDiv = $('.someDiv'),
    addTable = function(){
        var table = $('<table/>').appendTo(someDiv),
            i, tr,
            j, td;
        for (i = 0; i < 20; i++) {
            tr = $('<tr/>').appendTo(table);
            for (j = 0; j < 20; j++) {
                td = $('<td/>').appendTo(tr);
            }
        }
        return table
    };

$document.
    on('click.activate', '.someDiv table td', function() {
        $(this).toggleClass('active');
    }).
    on('mouseenter.hover', '.someDiv table td', function() {
        $(this).addClass('hover');
    }).
    on('mouseleave.hover', '.someDiv table td', function() {
        $(this).removeClass('hover');
    });

for (var i = 0; i < 5; i++)
    addTable();
someDiv.find('td:first').click();
pending…
with clone delegation
var $document = $(document),
    someDiv = $('.someDiv'),
    genTable = function(){
        var table = $('<table/>'),
            i, tr,
            j, td;
        for (i = 0; i < 20; i++) {
            tr = $('<tr/>').appendTo(table);
            for (j = 0; j < 20; j++) {
                td = $('<td/>').appendTo(tr);
            }
        }
        return table
    },
    cloneTable = function(table){
        return table.clone().appendTo(someDiv);
    },
    template = genTable();

$document.
    on('click.activate', '.someDiv table td', function() {
        $(this).toggleClass('active');
    }).
    on('mouseenter.hover', '.someDiv table td', function() {
        $(this).addClass('hover');
    }).
    on('mouseleave.hover', '.someDiv table td', function() {
        $(this).removeClass('hover');
    });

for (var i = 0; i < 5; i++)
    cloneTable(template);
someDiv.find('td:first').click();
pending…
with deep clone delegation
var $document = $(document),
    someDiv = $('.someDiv'),
    genTable = function(){
        var table = $('<table/>'),
            i, tr,
            j, td;
        for (i = 0; i < 20; i++) {
            tr = $('<tr/>').appendTo(table);
            for (j = 0; j < 20; j++) {
                td = $('<td/>').appendTo(tr);
            }
        }
        return table
    },
    cloneTable = function(table){
        return table.clone(true, true).appendTo(someDiv);
    },
    template = genTable();

$document.
    on('click.activate', '.someDiv table td', function() {
        $(this).toggleClass('active');
    }).
    on('mouseenter.hover', '.someDiv table td', function() {
        $(this).addClass('hover');
    }).
    on('mouseleave.hover', '.someDiv table td', function() {
        $(this).removeClass('hover');
    });

for (var i = 0; i < 5; i++)
    cloneTable(template);
someDiv.find('td:first').click();
pending…
with concat html delegation
var $document = $(document),
    someDiv = $('.someDiv'),
    genTable = function(){
        var table = $('<table/>'),
            i, tr,
            j, td;
        for (i = 0; i < 20; i++) {
            tr = $('<tr/>').appendTo(table);
            for (j = 0; j < 20; j++) {
                td = $('<td/>').appendTo(tr);
            }
        }
        return table
    },
    template = genTable().html(),
    tables = [];

$document.
    on('click.activate', '.someDiv table td', function() {
        $(this).toggleClass('active');
    }).
    on('mouseenter.hover', '.someDiv table td', function() {
        $(this).addClass('hover');
    }).
    on('mouseleave.hover', '.someDiv table td', function() {
        $(this).removeClass('hover');
    });

for (var i = 0; i < 5; i++)
    tables.push(template);
someDiv.append(tables.join(''));
someDiv.find('td:first').click();
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment