8
\$\begingroup\$

I need a function to get the value of the name attribute of each element with class="class". I was wondering what is the best way to do this, performance-wise.

Currently I'm using jQuery and doing it like this:

$("#Button").click(function() {
    var myElements = $(".class");
    for (var i=0;i<myElements.length;i++) {
        alert(myElements.eq(i).attr("name"));
    }
});

Alert is just to show what it does, of course. For the following HTML:

<input type="checkbox" class="class" name="1">
<input type="checkbox" class="nope" name="2">
<input type="checkbox" class="class" name="3">

It would issue:

alert("1")
alert("3")

I was wondering if using pure Javascript would be faster, or if there is any other (better) way of doing it. I apologize if this question is not on this website's scope, please move it to Stackoverflow if that's the case.

\$\endgroup\$
  • 3
    \$\begingroup\$ Please, always replace alert by console.log Alert is blocking code execution and forces you to click ok or press enter as many times as a result is found. \$\endgroup\$ – Apero Mar 21 '13 at 3:52
9
\$\begingroup\$

Pure JS vs jQuery

Pure JavaScript will be significantly faster as you can see by this jsPerf which pits document.getElementByClassName vs the jQuery selector. Here are the results for Chrome 25:

  • $('.class') - 4355 operations per second
  • getElementsByClassName('class') - 94636 operations per second

As you can see, for this simple operation the jQuery option is approximately 22 times slower than the pure-JavaScript equivalent. You can easily see why this is the case by checking out the jQuery development source, since the jQuery 'selector function' is so general it needs to do a lot of checks to see what the input is before it can act upon it.

Pure JS implementation

I've left the jQuery click event in as it looks like you already have a dependency on jQuery so no point changing the way you're hooking up your events.

jsFiddle

$("#Button").click(function() {
    var items = document.getElementsByClassName('class');
    for (var i = 0; i < items.length; i++)
        alert(items[i].name);
});

getElementsByClassName

Also note that I used getElementsByClassName. It is pretty important to choose the ideal selector if you care about performance. Since we care about all elements with a certain class we can immediately dismiss the others like getElementsByTagName and querySelectorAll and opt for the function that was built for finding elements of a particular class.

jQuery implementation

This would be my implementation using jQuery, notice that I didn't bother getting the jQuery object for this (ie. $(this)) because the plain JavaScript attribute is much easier in this case.

jsFiddle

$("#Button").click(function() {
    $(".class").each(function() {
        alert(this.name);
    });
});
\$\endgroup\$
  • \$\begingroup\$ Perfect. Although I like jQuery I avoid it when it can easily be done with pure Javascript. For some reason I couldn't make it work before, probably some dumb syntax error. \$\endgroup\$ – Alex Mar 21 '13 at 8:35
  • \$\begingroup\$ Ditto. Takes a while to get your head around all the JS functions, make sure you're looking at your browser errors to debug it. \$\endgroup\$ – Daniel Imms Mar 21 '13 at 8:36
  • 1
    \$\begingroup\$ Depending on what you want to do with the names you could use jQuery's .map() to get an array. \$\endgroup\$ – RoToRa Mar 21 '13 at 14:25
  • 1
    \$\begingroup\$ @RoToRa I think it would be just as useful as $(".class").each( function() {//stuff}); in this case, but thanks! \$\endgroup\$ – Alex Mar 21 '13 at 14:52
5
\$\begingroup\$

Instead of storing them in an array, you can use $.each function for looping through them. Like this:

$("#Button").click(function() {
    $(".class").each( function() {
        alert( $(this).attr("name") );
    }
});
\$\endgroup\$
3
\$\begingroup\$

To do this is in 'pure' JavaScript, you do something like this, if using ES6 syntax:

var elements = document.getElementsByClassName('class');
elements.forEach(e => { alert(e.name) });

For any browsers not supporting ES6 (including all versions of IE):

var elements = document.getElementsByClassName('class');
elements.forEach(function(e) { alert(e.name); });

If IE8 support is required:

var elements = document.querySelectorAll('.class');
for (var i = 0; i < elements.length; i++) {
  alert(elements[i].name);
}

Which will be a bit faster compared to using jQuery. However, jQuery will still be the shortest code:

$('.class').each(e => { alert(e.name); });
\$\endgroup\$
  • \$\begingroup\$ Thank you. I might be dealing with 100+ elements, since this will be used in a comments section. I'll do some benchmarking with both codes and give some feedback when everything is done. I was wondering if it would be possible to use document.getElementsByClassName() and a for loop instead. I tried but couldn't get it to work. I used the same for loop and document.getElementsByClassName('class')[i].name \$\endgroup\$ – Alex Mar 20 '13 at 22:45
1
\$\begingroup\$

You can use document.querySelectorAll to retrieve the desired elements:

var namedEls = document.querySelectorAll('input.class');
for (var i=0;i<namedEls.length;i+=1){
    console.log(namedEls[i].name);
} //=> 1, 3

Or as one liner to retrieve names as Array:

var names = [].slice.call(document.querySelectorAll('input.class'))
             .map(function(el){return el.name});
//=> names is now [1,3]
\$\endgroup\$
  • \$\begingroup\$ Why input[class="class"] and not input.class? (Unless you specifically want to exclude elements with multiple classes.) \$\endgroup\$ – RoToRa Mar 21 '13 at 14:23
  • \$\begingroup\$ No particular reason, so changed the answer. Doesn't change the results. \$\endgroup\$ – KooiInc Mar 24 '13 at 7:29
0
\$\begingroup\$
parent.querySelectorAll([name='value']);

Depending on your knowledge of your Dom, can be super efficient; you can select the parent node to search within or just go document if you have no specific Dom knowledge.

If using custom elements or custom name space it can be very powerful and requires no library add ons. Works in all modern browsers.

The platform is growing and can now do amazing things.

\$\endgroup\$

protected by Jamal Feb 20 at 23:32

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.