59

I am not asking what is the appropriate syntax for chaining, I know it could be something like:

$('myDiv').removeClass('off').addClass('on');

As far as I know chaining is one of the advantages against other famous frameworks. Can someone explain to me how chaining works here?

TylerH
  • 20,799
  • 66
  • 75
  • 101
isJustMe
  • 5,452
  • 2
  • 31
  • 47
  • 8
    None of the answers below are complete, please check the documentation on `.end()`: http://api.jquery.com/end/, as jQuery not only returns the object a function is operating on, but if the selector is changed mid-chain, it retains the history of the selectors used as well so that you can "go back" to a previous selector used. – VNO Sep 19 '11 at 18:16
  • 1
    Here's the design pattern: http://en.wikipedia.org/wiki/Fluent_interface – Joe Sep 19 '11 at 18:42
  • 3
    @Vibhu: OP wants to know how chaining works, not all the details of jQuery's implementation. *"...for a novice programer like me, I'm sure there is someone out there that can provide me with a explanation that allows me to understand how chaining works."* – user113716 Sep 19 '11 at 19:58
  • 2
    Got very good answers! thanks to everyone. – isJustMe Sep 19 '11 at 21:11
  • possible duplicate of [How does basic object/function chaining work in javascript?](http://stackoverflow.com/q/1099628/1048572) – Bergi Jun 11 '14 at 14:44

10 Answers10

73

If you have an object with certain methods, if each method returns an object with methods, you can simply call a method from the object returned.

var obj = {   // every method returns obj---------v
    first: function() { alert('first');   return obj; },
    second: function() { alert('second'); return obj; },
    third: function() { alert('third');   return obj; }
}

obj.first().second().third();

DEMO: http://jsfiddle.net/5kkCh/

user113716
  • 318,772
  • 63
  • 451
  • 440
  • 5
    Instead of `return obj`, can you say `return this`? Because I tested and it gives me the same result. – Derek 朕會功夫 Jan 04 '12 at 03:28
  • 2
    @Derek: You could do that, because `this` in the functions in the example will be the object each method was called on. –  Jan 04 '12 at 03:36
  • 1
    @Derek朕會功夫 I think that for people who are new-er to JavaScript the @squint answer's way of doing it (returning a reference to a variable instead of `this`) is clearer because `var that = this` seems to turn people off in my experience to wanting to learn programming, and they think it's hard. But I think your suggestion is clearer because it makes it more obvious how you might go about implementing multiple "depths" of chains – tacos_tacos_tacos Jul 31 '15 at 08:04
  • how accessing like array works, `$('a')[0]` gives first element – Muhammad Umer Oct 12 '15 at 21:50
  • Since those functions contain 'obj' in their closure scope, doesn't this create a circular reference? Returning 'this' avoids that problem, so it's probably what you should do. – Dave Branton Feb 27 '18 at 23:41
28

All that it is doing is returning a reference to this when the method finishes. Take this simple object for example:

 var sampleObj = function()
 {
 };

 sampleObj.prototype.Foo = function()
 {
     return this;
 };

You could chain these calls all day because you return a reference to this:

var obj = new sampleObj();
obj.Foo().Foo().Foo().Foo() // and so on

jQuery simply performs an operation, then returns this.

Tejs
  • 40,736
  • 10
  • 68
  • 86
7

Basically the first function call $('myDiv') returns a jQuery object, then each subsequent call returns the same one.

Loosely,

var $ = function(selector) {
   return new jQuery(selector);
};

jQuery.prototype.removeClass = function(className) {
   // magic
   return this;
}
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
4
return $this;

each jQuery function returns an instance of the jQuery class, which can then have methods called on it. you could break it down, and this code would have the same effect.

jQuery_obj = $('myDiv');
jQuery_obj = jQuery_obj.removeClass('off');
jQuery_obj = jQuery_obj.addClass('on');
GSto
  • 41,512
  • 37
  • 133
  • 184
4

The point is that a function must evaluate to the "parent" function. So e.g.

foo().bar().test();

has to evaluate to:

foo().test();

so that you can call another function on foo(). To do this, you can return this:

function foo() {
    // empty, nothing interesting here
}

foo.prototype.bar = function() {
    return this;
}

foo.prototype.test = function() {
    return this;
}

Then,

var something = new foo();
something.bar() === something; // true

And because of this:

something.bar().test() === something.test(); // true

So because something.bar() evaluates to something, you can immediately call the second function in one go.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
4

In chaining parent function/method returns an object which is then used by the child function/method, and things go on such a way. In short the jQuery or $ returns itself (an object) which allows the chaining.

It is the same mechanism below

var obj=$('input');    //returns jQuery object
var obj1=obj.val('a'); //returns jQuery object
var obj2=obj1.fadeOut();//returns jQuery object

It looks like this if it is done with chaining

$('input').val('a').fadeOut();
Muhammad Usman
  • 12,439
  • 6
  • 36
  • 59
0

Here is an example of conditional callback chaining, like is used on the $.ajax jQuery function.

// conditional callback function example
myFunction = function () {

    // define event callback prototypes without function parameter
    var callback_f = new Object;
    callback_f.callback1 = function () { return callback_f; };
    callback_f.callback2 = function () { return callback_f; };

    if ([condition]){
        // redefine the callback with function parameter 
        // so it will run the user code passed in
        callback_f.ReturnPlayer = function (f) { f(); return callback_f; };
    }else{ 
        callback_f.NewPlayer = function (f) { f(); return callback_f; };
    }

    return callback_f;
}
Himanshu
  • 31,810
  • 31
  • 111
  • 133
Matthew.Lothian
  • 2,072
  • 17
  • 23
0

One of the way to chaining, check demo .

test("element").f1().f2().f3()
Shoib Mohammed A
  • 298
  • 4
  • 12
0

Chaining is used to connect multiple events and functions in a selector.

To run multiple jQuery commands, one after the other, on the same element(s). Generally chaining uses the jQuery built in functions that makes compilation a bit faster.

It makes your code short and easy to manage and it gives better performance,

Eaxample

Without Chaining

$(document).ready(function(){
    $('#dvContent').addClass('dummy');
    $('#dvContent').css('color', 'red');
    $('#dvContent').fadeIn('slow');
});

With Chaining

$(document).ready(function(){
    $('#dvContent').addClass('dummy')
          .css('color', 'red')
          .fadeIn('slow');     
});

Note: The chain starts from left to right. So left most will be called first and so on.

Community
  • 1
  • 1
Srikrushna
  • 4,366
  • 2
  • 39
  • 46
0

Chaining allows us to run multiple jQuery methods (on the same element) within a single statement.

The following example chains together the css(), slideUp(), and slideDown() methods. The "p1" element first changes to red, then it slides up, and then it slides down :

 $("#p1").css("color", "red").slideUp(2000).slideDown(2000); 
sn99
  • 843
  • 8
  • 24
  • The OP didn't ask what chaining is; they asked how chaining works. The [answer from user113716](https://stackoverflow.com/a/7475375/597460) explains it. – squidbe Jun 06 '23 at 22:57