jQuery: What is more efficient? Many ID specific selectors, or one “Contains Prefix Selector”

I have a snippet of JavaScript in a project that caches an array of jQuery objects (anchor tags) on a dashboard:

$.extend(cache, {
    dashboard : {
        buttons : [
            $('#dash-new-lead'),               $('#dash-jobs-calendar'),
            $('#dash-view-lead'),              $('#dash-sales-reports'),
            $('#dash-search-leads'),           $('#dash-new-job'),
            $('#dash-dispatch-jobs'),          $('#dash-dispatch-reports'),
            $('#dash-manage-employees'),       $('#dash-manage-trucks'),
            $('#dash-finalize-jobs'),          $('#dash-payment-profiles'),
            $('#dash-employee-statements'),    $('#dash-company-statements'),
            $('#dash-finance-reports'),        $('#dash-admin-sources'),
            $('#dash-admin-statuses'),         $('#dash-admin-companies'),
            $('#dash-admin-groups'),           $('#dash-admin-users'),
            $('#dash-admin-dispositions'),     $('#dash-search-jobs'),
            $('#dash-jobs-calendar-dispatch'), $('#dash-new-lead-dispatch'),
            $('#dash-finance-notices')
        ]
    }
});

Each link is styled later (using $.each) as a button. Each link gets a unique jQuery UI icon (hence the id's instead of just a class selector). Depending on a user's access level some links may or may not exist in the DOM.

I'm wondering now if it would be more efficient to use jQuery's Contains Prefix Selector:

$.extend(cache, {
    dashboard : {
        buttons : $('a[id|="dash-"]')
    }
});
  1. Pro: Fewer references to the jQuery Object = faster
  2. Con: jQuery cannot use document.getElementByID = slower

Answers


It'll depend very much on the browser, so you'll need to test to be sure.

Because 'a[id|="dash"]' (notice I removed the -) appears to be a valid querySelectorAll() selector, any browsers that support that method (which includes IE8) should have very good performance.

Because you're including the tagName, browsers that don't support querySelectorAll() will (I believe) use getElementsByTagName(), so the filter will only be applied to the <a> elements it finds.

It should help as well if you're able to limit the query to a narrower context than the document.

Note also that according to this test, the performance of getElementById() isn't terribly exciting in IE6 and IE7. And again IE8 does support querySelectorAll(), though it wouldn't be bad to make sure it succeeds with that particular selector. If not, the query will default to Sizzle's engine.


Here's a test using that selector directly through querySelectorAll(). You can run it in different browsers to see where it is supported.


Note also that getElementsByClassName() isn't supported before IE9, so I doubt that using a class will offer any great performance improvements over 'a[id|="dash"]'. The exception being Firefox3, which does support getElementsByClassName(), and not querySelectorAll().


You can make a single selector that contains all the identities:

$.extend(cache, {
  dashboard : {
    buttons : $('#dash-new-lead,#dash-jobs-calendar,#dash-view-lead,#dash-sales-reports,#dash-search-leads,#dash-new-job,#dash-dispatch-jobs,#dash-dispatch-reports,#dash-manage-employees,#dash-manage-trucks,#dash-finalize-jobs,#dash-payment-profiles,#dash-employee-statements,#dash-company-statements,#dash-finance-reports,#dash-admin-sources,#dash-admin-statuses,#dash-admin-companies,#dash-admin-groups,#dash-admin-users,#dash-admin-dispositions,#dash-search-jobs,#dash-jobs-calendar-dispatch,#dash-new-lead-dispatch,#dash-finance-notices')
  }
});

I would however consider adding a class to the buttons so that it's easy to target them using a simple selector. That would make it easier to maintain the code.


As well as each of your elements having its unique id (dash-new-jobs etc), give it a class too (class='dash-button').

You can then refer to the whole collection efficiently using e.g.

$.extend(cache, {
    dashboard : {
        buttons : $('.dash-button')
    }
});

And if you need to give them all different icons like you mentioned, use their unique ID:

$('.dash-button').each(function() {
    // do something based on $(this).attr('id'),
    // which will be dash-new-job/dash-whatever
});

Efficient (though as the others have said, do performance tests if you're unsure!), and clean/easy to understand code (much cleaner than using 'contains' selector!).


Need Your Help

how to improve memory usage when using GenericItemSimilarity in mahout(taste)

mahout

As we known, in genericItemSimilarity similarity between item1 and item2 is precomputed.

Why do all the variants of SHA256 appear as SHA256Managed?

c# hash md5 checksum sha256

I'm writing an extension method that simplifies the creation of hashes by removing a ton of boilerplate, my problem is however that whenever I step through the code, I can see that it always picks

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.