Search code examples
javascriptjquerychaining

How does jQuery accomplish chaining of commands?


I consider myself (at best) a mid-level JavaScript guy...and of course...I want to understand HOW some things are accomplished so I can write better code. As such, I've been looking under-the-hood of jQuery trying to uderstand it a little more about how certain things are accomplished.

For example:
jQuery handles the case where IE and Opera return items by name instead of ID by doing the following:

// HANDLE: $("#id")
else 
{
    var elem = document.getElementById( match[3] );

    // Handle the case where IE and Opera return items
    // by name instead of ID
    if ( elem && elem.id != match[3] )
        return jQuery().find( selector );

    // Otherwise, we inject the element directly into the jQuery object
    var ret = jQuery( elem || [] )
    ret.context = document;
    ret.selector = selector;

    return ret;
}

...okay that's easy!

But a typical line of jQuery code chains a series of commands together:

$('#someElementId').fadeIn().css({ ...Some CSS Properties ... });

Now...I 'think' the chaining portion is handled in the following area:

jQuery.extend = jQuery.fn.extend = function() { ... };

I'm combing through this area...and I see HOW a single command is processed...but I don't really see WHERE or HOW a chain-of-commands are managed. So I am obviously missing something.

So My Question Is:

  1. How does jQuery implement chaining of selectors?

Solution

  • As per your comment:

    This is from the example here: http://en.wikipedia.org/wiki/Fluent_interface#JavaScript With extra comments

    var Car = function() {
    
            var speed, color, doors;
    
            this.setSpeed = function(speed) {
                    this.speed = speed;
                    **//Returns the reference to the calling `car` object** 
                    return this; 
            };
    
            this.setColor = function(color) {
                    this.color = color;
                    **//Returns the reference to the calling `car` object** 
                    return this; 
            };
    
            this.setDoors = function(doors) {
                    this.doors = doors;
                    **//Returns the reference to the calling `car` object** 
                    return this; 
            };
    
    };
    
    // Fluent interface
    **//Each method returns a reference to the object itself**
    **//so the next method chain is refering back to the previous returned value**
    **//ie - itself, the orginal object that started the call chain**
    myCar = new Car();
    myCar.setSpeed(100).setColor('blue').setDoors(5);
    
    // Example without fluent interface
    **// normal, non fluent style, where each method returns Void**
    **// so you need to start with the object reference yourself each time**
    myCar2 = new Car();
    myCar2.setSpeed(100);
    myCar2.setColor('blue');
    myCar2.setDoors(5);