More on jQuery id selection performance
Published
In response to Ron’s comment on the attr('id')
vs [0].id
post last week asking about the jQuery.fn.prop
’s vs jQuery.fn.attr
’s performance, I extended the program to include prop
and enabled profiling across all browsers (thanks to time.js). The program also does the tests a little more thoroughly, running 1000000 operations 5 times per each operation and averages the result.
Some of the result surprised me a little, in particular Safari beating Chrome on d.attr('id')
but nothing else, and d.prop('id')
was the clear winner.

These charts are going to be a lot nicer when we can start using IE10 ;)
Chrome 22
d.attr('id'): 1164ms d.prop('id'): 947ms d[0].id: 56ms d.get(0).id: 64ms d[0].getAttribute('id'): 95ms
Firefox 16
d.attr('id'): 2787ms d.prop('id'): 2198ms d[0].id: 161ms d.get(0).id: 171ms d[0].getAttribute('id'): 188ms
IE 9
d.attr('id'): 5051ms d.prop('id'): 2780ms d[0].id: 273ms d.get(0).id: 298ms d[0].getAttribute('id'): 793ms
Opera 12
d.attr('id'): 1534ms d.prop('id'): 1377ms d[0].id: 312ms d.get(0).id: 324ms d[0].getAttribute('id'): 354ms
Safari 5.1
d.attr('id'): 1082ms d.prop('id'): 997ms d[0].id: 140ms d.get(0).id: 155ms d[0].getAttribute('id'): 190ms
Test
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://remysharp.com/time.packed.js"></script>
<script>
var numberOfTypeTests = 5;
var numberOfIdTests = 1000000;
var div;
$().ready(function () {
$('#run').click(run);
$('#report').click(function () { time.report(); });
div = $('#test');
time.setReportMethod(reportMethod);
});
function run() {
for (var i = 0; i < numberOfTypeTests; i++) { testAttr(); }
for (var i = 0; i < numberOfTypeTests; i++) { testProp(); }
for (var i = 0; i < numberOfTypeTests; i++) { testConvert(); }
for (var i = 0; i < numberOfTypeTests; i++) { testGet(); }
for (var i = 0; i < numberOfTypeTests; i++) { testGetAttribute(); }
time.report();
}
function testAttr() {
test('d.attr(\'id\')', function (d) { d.attr('id'); });
}
function testProp() {
test('d.prop(\'id\')', function (d) { d.prop('id'); });
}
function testConvert() {
test('d[0].id', function (d) { d[0].id; });
}
function testGet() {
test('d.get(0).id', function (d) { d.get(0).id; });
}
function testGetAttribute() {
test('d[0].getAttribute(\'id\')', function (d) { d[0].getAttribute('id'); });
}
function test(name, f) {
time.start(name);
for (var i = 0; i < numberOfIdTests; i++) { f(div); }
time.stop(name);
}
function reportMethod(t) {
var report = '';
for (var i = 0; i < t.length / numberOfTypeTests ; i++) { // Type test
var total = 0.0;
for (var j = 0; j < numberOfTypeTests; j++) {
total += t[i * numberOfTypeTests + j].delta;
}
var avg = Math.round(total / numberOfTypeTests);
report += t[i * numberOfTypeTests].name + ': ' + avg + 'ms<br />';
}
$('#output').html(report);
}
</script>
</head>
<body>
<button id="run">Run tests</button>
<div id="test"></div>
<div id="output"></div>
</body>
</html>