Bug Tracker

Ticket #1316 (closed enhancement: fixed)

Opened 2 years ago

Last modified 1 year ago

[Patch] Significantly speed up $('#id')

Reported by: Chainfire Assigned to: john
Type: enhancement Priority: minor
Milestone: 1.1.4 Component: core
Version: 1.1.3 Keywords: optimization
Cc: Needs: Review

Description

$('#id') is significantly slower than $(document.getElementById('id')) . Ofcourse using jQuery should give a small performance hit, but in some cases it can be as much as 40x slower. As discussed in the IRC channel, $('#id') is used a lot, this special often-used case warrants optimization.

Result of this patch, $('#id') is about 10% slower than $(document.getElementById('id')) as opposed to the earlier 4000%.

jQuery.js: jQuery.fn.init (line 165 in 1.1.3a)

		// Handle HTML strings
		if ( typeof a  == "string" ) {
			// HANDLE: $(html) -> $(array)
			var m = /^[^<]*(<(.|\s)+>)[^>]*$/.exec(a);
			if ( m )
				a = jQuery.clean( [ m[1] ] );
			// HANDLE: $(expr)
			else {
				if (!c && /^#[A-Za-z0-9_]+$/.test(a) && (elm = document.getElementById(a.substring(1)))) {
					a = elm;
				} else {
					return new jQuery( c ).find( a );
				}
			}
		}

Attachments

Change History

Changed 2 years ago by rformato

I managed to write a version that compresses itself a bit more and includes even - and : as valid chars for the id. Compressed, the code is 49 bytes longer than jQuery 1.1.3a (a bit too much but I'm not able to make it better)

The regex, if successful, will return a not null m[1] when one passes an html string or a not null m[3] when one passes in id selector.

However, the fast id selector can be used only when there's no valid context, so m && ( m[1] && !c ) verify both the cases.

If the id case is true, document.getElementById( m[3] ) || [] will avoid to store a null value just in case getElementById does not find the desired element.

    // Handle HTML strings
    if ( typeof a  == "string" ) {
        // HANDLE: $(html) -> $(array) and a fast $('#id')->$(element);
        var m = /^[^<]*(<(.|\s)+>)[^>]*$|^#([-\w\d:]+)$/.exec(a);
        if ( m && ( m[1] || !c ) )
              a = m[1] ? jQuery.clean( [ m[1] ] ) : document.getElementById( m[3] ) || [];
        // HANDLE: $(expr)
        else
            return new jQuery( c ).find( a );
    }

Changed 1 year ago by john

  • owner set to john

Changed 1 year ago by john

  • status changed from new to closed
  • version changed from 1.1.2 to 1.1.3
  • resolution set to fixed
  • milestone changed from 1.1.3 to 1.1.4

Fixed in SVN rev [2821].

Changed 1 year ago by john

Demo page can be found here: http://dev.jquery.com/~john/ticket/1316/

Note: See TracTickets for help on using tickets.