¿Cómo funciona el encadenamiento de objetos o métodos en jQuery?
No estoy preguntando cuál es la sintaxis apropiada para encadenar, sé que podría ser algo como:
$('myDiv').removeClass('off').addClass('on');
Hasta donde yo sé, el encadenamiento es una de las ventajas frente a otros marcos famosos. ¿Alguien puede explicarme cómo funciona el encadenamiento aquí?
Si tiene un objeto con ciertos métodos, si cada método devuelve un objeto con métodos, simplemente puede llamar a un método desde el objeto devuelto.
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();
DEMOSTRACIÓN: http://jsfiddle.net/5kkCh/
Todo lo que hace es devolver una referencia a this
cuándo finaliza el método. Tomemos este objeto simple, por ejemplo:
var sampleObj = function()
{
};
sampleObj.prototype.Foo = function()
{
return this;
};
Podrías encadenar estas llamadas todo el día porque devuelves una referencia a this
:
var obj = new sampleObj();
obj.Foo().Foo().Foo().Foo() // and so on
jQuery simplemente realiza una operación y luego devuelve this
.
Básicamente, la primera llamada a la función $('myDiv')
devuelve un objeto jQuery, luego cada llamada posterior devuelve el mismo.
Flojamente,
var $ = function(selector) {
return new jQuery(selector);
};
jQuery.prototype.removeClass = function(className) {
// magic
return this;
}
return $this;
cada función jQuery devuelve una instancia de la clase jQuery, que luego puede tener métodos llamados. podrías descomponerlo y este código tendría el mismo efecto.
jQuery_obj = $('myDiv');
jQuery_obj = jQuery_obj.removeClass('off');
jQuery_obj = jQuery_obj.addClass('on');
El punto es que una función debe evaluarse como la función "principal". Entonces, por ejemplo
foo().bar().test();
tiene que evaluar para:
foo().test();
para que puedas llamar a otra función foo()
. Para hacer esto, puedes return this
:
function foo() {
// empty, nothing interesting here
}
foo.prototype.bar = function() {
return this;
}
foo.prototype.test = function() {
return this;
}
Entonces,
var something = new foo();
something.bar() === something; // true
Y a causa de esto:
something.bar().test() === something.test(); // true
Entonces, como something.bar()
se evalúa como something
, puedes llamar inmediatamente a la segunda función de una sola vez.