How does the jQuery stack work?


When I learned how to use the .end method of jQuery, I realized that it was a powerful tool that ensures a lot of expressiveness to the code (and I was soon seeing how to integrate it with my plugins ). Although I have a basic understanding of how it works:

$(meuSeletor)       // Seleciona um conjunto de elemtentos   [meuSeletor]
    .fazAlgo()      // Faz algo com ele, mantém o conjunto   [meuSeletor]
    .find(sub)      // Acha um subconjunto, mas empilha o anterior [sub, meuSeletor]
        .fazAlgo()  // Faz algo com esse subconjunto               [sub, meuSeletor]
    .end()          // "Desempilha": volta o que tinha antes [meuSeletor]
    .fazAlgo();     // Faz algo com o conjunto original      [meuSeletor]

Some functions like andSelf and

asked by anonymous 05.02.2014 / 01:30

2 answers


I looked at the source code is simpler than I thought. The stack was implemented as a chain of objects. Each jQuery object can have a prevObject property, pointing to the previous object. Therefore:

var o = $(meuSeletor);
var sub = o.find(sub);
sub.prevObject === o; // true

end returns prevObject , or an object jQuery empty (I think):

end: function() {
    return this.prevObject || this.constructor(null);

pushStack creates a new object with the elements passed and the same object that invoked it, and sets prevObject to the latter:

pushStack: function( elems ) {

    // Build a new jQuery matched element set
    var ret = jQuery.merge( this.constructor(), elems );

    // Add the old object onto the stack (as a reference)
    ret.prevObject = this;
    ret.context = this.context;

    // Return the newly-formed element set
    return ret;

The addBack creates a new object, adding prevObject to the current one (thanks to Gabriel Santos for locating the code):

addBack: function(selector) { 
    return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector)); 
05.02.2014 / 04:28

It's quite simple, in fact, the selection functions return the element itself, so you can use the so-called chaining to give a natural continuity in the script.

It's like doing something like this:

$.fn.test = function() {
    return this.each(function(){/* faz algo com cada elemento*/});

The usage would look like this: $('div').test();

And you could continue picking up the children paragraphs for example:


So when you use a function that returns a node, it executes its scope and returns the same node so that it continues to be used ... It's like you walk through the DOM.

Here you get to the element li and add a class:


Here from the same point you stopped, you can go up to the parent element list of the current list item and perform another action such as hiding for example:


This slows down writing and dramatically improves performance in certain scripts.

If you want to see how a plugin does this on the inside you can see the standards developed by Addy Osmani from Google, I even contribute in this one: Best Options

05.02.2014 / 01:42