first-pass (v11)

Revision 11 of this benchmark created on


Preparation HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js"></script>
<table id="test_table">
  <tbody id="test_tbody">
    Test
  </tbody>
</table>
<style>
  .active{ background:red; font-size:30px; }
</style>
<script type="text/template" id="template">
<% for(var i = 0; i < rows; i++){ %>
    <tr>
    <% for(var j = 0; j < data.length; j++){ %>
         <td><%= data[j] %></td>
    <% } %>
    </tr>
<% } %>
</script>

Setup

// Tables
    var numItems = 200; // items/cols
    var rows = 200;
    var tbody = document.getElementById('test_tbody');
    var $tbody = $('#test_tbody');
    var tr, td;
    var $tr, $td;
    
    // Data arrays
    var dataArray = [];
    var dataArrayObject = [];
    
    // Fragments
    var frag = document.createDocumentFragment();
    var frag2 = document.createDocumentFragment();
    
    // Populate data
    for (var i = 0; i < numItems; i++) {
        dataArray[i] = i;
    }
    
    for (var i = 0; i < numItems; i++) {
        dataArrayObject[i] = {};
        dataArrayObject[i]["id"] = i;
    }
    
    var predefinedLengthArray = new Array(50);
    for (i = 0; i < numItems; i++) {
        predefinedLengthArray[i] = dataArray[i];
    }
    
    
    function drawDocumentFragTable(cols) {
        for (var i = 0; i < rows; i++) {
            tr = document.createElement('tr');
            for (var j = 0; j < cols.length; j++) {
                td = document.createElement('td');
                td.appendChild(document.createTextNode(cols[j]));
    
                frag2.appendChild(td);
            }
            tr.appendChild(frag2);
            frag.appendChild(tr);
        }
        tbody.appendChild(frag);
    }
    
    function drawDocumentFragTable2(cols) {
        for (var i = 0; i < rows; i++) {
            tr = document.createElement('tr');
            for (var j = 0; j < cols.length; j++) {
                td = document.createElement('td');
                td.appendChild(document.createTextNode(cols[j]));
    
                tr.appendChild(td);
            }
            //tr.appendChild(frag2);
            tbody.appendChild(tr);
        }
        //tbody.appendChild(frag);
    }
    
    
    function eventsNoDelegation() {
        $('table td').on('click', function () {
            $(this).toggleClass('active');
        });
    }
    
    function eventsWithDelegation() {
        $('table').on('click', 'td', function () {
            $(this).toggleClass('active');
        });
    }
    
    
    // Array object, no delegation, jQuery for table creation.
    var moduleA = function () {
    
        return {
    
            data: dataArrayObject,
    
            init: function () {
                this.addTable();
                this.addEvents();
            },
    
            addTable: function () {
    
                for (var i = 0; i < rows; i++) {
                    $tr = $('<tr></tr>');
                    for (var j = 0; j < this.data.length; j++) {
                        $tr.append('<td>' + this.data[j]["id"] + '</td>');
                    }
                    $tr.appendTo($tbody);
                }
    
            },
            addEvents: function () {
                eventsNoDelegation();
            }
    
        };
    
    }();
    
    
    
    
    // Simple array, no delegation, jQuery for table creation
    var moduleB = function () {
    
        return {
    
            data: dataArray,
    
            init: function () {
                this.addTable();
                this.addEvents();
            },
            addTable: function () {
                for (var i = 0; i < rows; i++) {
                    $tr = $('<tr></tr>');
                    for (var j = 0; j < this.data.length; j++) {
                        $tr.append('<td>' + this.data[j]["id"] + '</td>');
                    }
                    $tr.appendTo($tbody);
                }
            },
            addEvents: function () {
                eventsNoDelegation();
            }
    
        };
    
    }();
    
    
    var moduleC = function () {
    
        return {
    
            data: dataArray,
    
            init: function () {
                this.addTable();
                this.addEvents();
            },
            addTable: function () {
                drawDocumentFragTable(this.data);
            },
            addEvents: function () {
                eventsWithDelegation();
            }
    
        };
    
    }();
    
    
    // Simple array, delegation, documentFragment
    var moduleD = function () {
    
        return {
    
            data: dataArray,
    
            init: function () {
                this.addTable();
                this.addEvents();
            },
            addTable: function () {
                drawDocumentFragTable2(this.data);
            },
            addEvents: function () {
                eventsWithDelegation();
            }
    
        };
    
    }();
    
    
    // Simple array, delegation, documentFragment, prototypes
    moduleE = function () {};
    
    moduleE.prototype.data = dataArray;
    moduleE.prototype.init = function () {
        this.addTable();
        this.addEvents();
    };
    
    moduleE.prototype.addTable = function () {
        drawDocumentFragTable(this.data);
    };
    
    moduleE.prototype.addEvents = function () {
        eventsWithDelegation();
    };
    
    
    var modE = new moduleE();
    
    
    // Same, but with a predefined length array
    moduleF = function () {};
    
    moduleF.prototype.data = predefinedLengthArray;
    moduleF.prototype.init = function () {
        this.addTable();
        this.addEvents();
    };
    moduleF.prototype.addTable = function () {
        drawDocumentFragTable(this.data);
    };
    moduleF.prototype.addEvents = function () {
        eventsWithDelegation();
    };
    
    var modF = new moduleF();
    
    
    // Same, but with underscore templating
    moduleG = function () {};
    
    moduleG.prototype.data = dataArray;
    moduleG.prototype.init = function () {
        this.addTable();
        this.addEvents();
    };
    moduleG.prototype.addTable = function () {
        var template = _.template($('#template').text());
        var html = template({'data' : this.data, 'rows': rows});
        $tbody.append(html);
    };
    moduleG.prototype.addEvents = function () {
        eventsWithDelegation();
    };
    
    var modG = new moduleG();

Teardown


    rows = null;
    dataArray = null;
    dataArrayObject = null;
    predefinedLengthArray = null;
    
    $tbody.empty();
    
    tbody = null;
    $tbody = null;
    
    tr = null;
    td = null;
    $tr = null;
    $td = null;
    frag = null;
    frag2 = null;
    moduleA = null;
    moduleB = null;
    moduleC = null;
    moduleD = null;
    moduleE = null;
    moduleF = null;
    moduleG = null;
    modE = null;
    modF = null;
    modG = null;
    
    // Remove all event handlers for these
    $("table td").off("click", "**");
  

Test runner

Ready to run.

Testing in
TestOps/sec
Module A
// Module A - no event delegation, array objects, jQuery for table creation
moduleA.init();
ready
Module B
// Module B - no event delegation, simple arrays, jQuery for table creation
moduleB.init();
ready
Module C
// Module C - event delegation, simple arrays, jQuery for table creation
moduleC.init();
ready
Module D
// Module D - event delegation, simple arrays, documentFragment for table creation
moduleD.init();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.