How Does Jquery Chaining Work

How do object or method chaining work in jQuery?

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/

How can jQuery do method chaining?

//function returning an object is a possibility. bar has access to elem because of
// the shared scope
function foo ( elem ) {
return {
bar : function () {
return elem.id;
}
};
}

In this one, the foo function returns an object containing whatever methods you wish. So when you call foo, you receive this:

{
bar : function () {
return elem.id;
}
}

elem is present from your call to foo. If you were to add a console.log( elem ) at the top of bar, you'd see that it's the same thing as what you passed to foo.

//this is kinda how jQuery does it:
var foo = (function() {
function foo ( elem ) {
this.elem = elem;
}

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

return function ( elem ) {
return new foo( elem );
};
}());

This is a little more complex, and actually divided into two.

function foo ( elem ) {
this.elem = elem;
}

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

Who doesn't love prototypical inheritance mixed with classical inheritance names? Anyway...functions act as both regular functions and as constructors. Meaning, when called with the new keyword, two special things happen:

  1. this inside of the foo refers to a freshly made copy of foo.prototype
  2. foo.prototype is returned (unless foo returns an object)

Note that foo.prototype isn't a magic value. It's just like any other object property.

So, inside the foo function/constructor, we're merely setting foo.prototype.elem, but not directly. Think of it like this (a little inaccurate, but it'll do): foo.prototype is the blueprint of a product. Whenever you wish to make more, you use the blueprint - duplicate what's inside, pass it along. Inside of foo, this refers to such a replication of the blueprint.

However, by explicitly setting values on foo.prototype, we're altering the blueprint itself. Whenever foo is called, it'll be called with this altered blueprint.

Finally, once foo is finished, the replication (the duplicated blueprint, but after foo has done stuff with it) is returned. This replication contains the original blueprint, and everything else we might have added - in this example, elem.

var foo = (function() {
...
return function ( elem ) {
return new foo( elem );
};
}());

We create a nameless function and immediately execute it.

(function () {
console.log( 'meep' );
}());

//is the equivalent of:
var something = function () {
console.log( 'meep' );
};
something();
something = undefined; //we can no longer use it

//and of this
function () {
console.log( 'meep' );
}(); //<--notice the parens
//however, it's considered good practice to wrap these self-executing-anonymous-functions
// in parens

Like all other functions, they can return values. And these values can be captured into variables.

var answer = (function () {
return 42;
}());
answer ==== 42;

var counter = (function () {
var c = 0;
return function () {
return c++;
};
}());
//counter is now a function, as a function was returned
counter(); //0
counter(); //1
counter(); //2...

So:

var foo = (function () {
...
return function ( elem ) {
...
};
}());

Returns a function which receives an argument, and that function is now assigned to foo.

The insides of the function:

return new foo( elem );

Is to ensure the special conditions I've spoken about above - it ensures that a new copy of the blueprint is manufactured, by explicitly doing the new operation. This can actually be replicated like this:

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

As long as you always call foo with the new keyword.

How does jQuery chain functions while still returning an array?

Using the jQuery source code viewer site the definition for $ (http://james.padolsey.com/jquery/#v=1.9.1&fn=$) is as follows:

$

function (selector, context) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init(selector, context, rootjQuery);
}

Notice it is returning from init(). Inside of init (http://james.padolsey.com/jquery/#v=1.9.1&fn=init) we see that at the end it calls a function called makeArray:

init

function (selector, context, rootjQuery) {
var match, elem;

// rest of function defintion

return jQuery.makeArray(selector, this);
}

Which brings us to the answer to the question 'How does jQuery chain functions while still returning an array?'

makeArray (http://james.padolsey.com/jquery/#v=1.9.1&fn=jQuery.makeArray) looks like this:

makeArray

function (arr, results) {
var ret = results || [];

if (arr != null) {
if (isArraylike(Object(arr))) {
jQuery.merge(ret, typeof arr === "string" ? [arr] : arr);
} else {
core_push.call(ret, arr);
}
}

return ret;
}

jQuery - Chaining custom functions

You need to return current element context, i.e. this from you custom method.

$.fn.foo = function() {  var html = '<div class="foo"></div>';  if ($(this).hasClass('somthing')) {    $(this).prepend(html);  }  return this; //The magic statement}
$.fn.bar = function() { var html = '<h3>bar</h3>'; $(this).find('.foo').prepend(html); return this; //The magic statement}
$('body').addClass('somthing').foo().bar();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

How this code works? (jQuery chaining)

This is due to the nature of append(function) and the difference in scope between the initial this and the one inside the function in your code.

Per the jQuery documentation at http://api.jquery.com/append/#append-function, append(function) operates on "each element in the set of matched elements. [...] Within the function, this refers to the current element in the set."

So, in your code, this.filter("a") is a jQuery object containing any matching elements, while this.href within the function itself represents each of those elements in turn during the iteration through the collection. Hence, the text is appended to all of the matching elements.

jQuery chaining order

Chaining itself doesn't guarantee order of execution, it only returns the previous jQuery context so that you'll be able to further work with it in a fluent way.

In your specific case, the invocation of slideUp and slideDown functions takes time to complete (because of their animated nature), but jQuery will not wait for them to finish before calling further (chained) methods.

You need to pass a callback instead:

$("#p1")
.css("color", "red")
.slideUp(2000, function() {
$(this).slideDown(2000, function() {
$(this).css("color", "blue");
});
});

See Fiddle

Javascript JQuery chaining

So I was wondering how can JQuery return both the nodelist and itself to allow chaining ?

It doesn't.

It only returns itself (which it an object).

That object has a property called 0 which contains the first element in the array of elements. It also has a property called html which contains a function.

How does basic object/function chaining work in javascript?

In JavaScript Functions are first class Objects. When you define a function, it is the constructor for that function object. In other words:

var gmap = function() {
this.add = function() {
alert('add');
return this;
}

this.del = function() {
alert('delete');
return this;
}

if (this instanceof gmap) {
return this.gmap;
} else {
return new gmap();
}
}
var test = new gmap();
test.add().del();

By assigning the

new gmap();
to the variable test you have now constructed a new object that "inherits" all the properties and methods from the gmap() constructor (class). If you run the snippet above you will see an alert for "add" and "delete".

In your examples above, the "this" refers to the window object, unless you wrap the functions in another function or object.

Chaining is difficult for me to understand at first, at least it was for me, but once I understood it, I realized how powerful of a tool it can be.

Why does chaining on multiple lines work in jquery?

delay(), fadeIn(), and fadeOut() all work by applying operations to the internal animation queue that jQuery maintains. As such, each call adds operations to the queue, and they (the queued operations) execute in the order they are added on the queue.

http://api.jquery.com/delay/ makes reference to this queue as the second argument, which if not provided defaults to the fx queue.



Related Topics



Leave a reply



Submit