jQuery prototype and constructor function chaining

10,064

Solution 1

It's a programming technique called function chaining.

You can see more on this here: How does basic object/function chaining work in javascript?

Solution 2

You know, this quite intrigued me. You've accepted an answer already, but let me just post mine in the event that it proves useful. There is a fiddle created here

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

jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    context: null,
    isReady: null,
    init: function( selector, context ) {
        if (selector === document){
            this.context = document;
            this.selector = document;
        }
        console.log(this);
        return this;
    },
    ready: function(func){
        var args = Array.prototype.slice.call(this, arguments),
            boundReadyFunc = func.bind(this, args.slice(1));

        if (this.isReady){
            func();
        }
        else {
            document.addEventListener( "DOMContentLoaded", this.onReady.bind(this, func), false );
        }
    },
    onReady: function(func){
        console.log("onready");
        this.isReady = true;
        func.call(this);
    },
};

jQuery.fn.init.prototype = jQuery.fn;
jQuery(document).ready(function(){
    alert("Hey, here I am");
});

Let me try to explain how this works.

Every time you call something like $(selector), a new jQuery instance is created, with the options that you have provided (see return new jQuery.fn.init( selector, context ););

For the sake of convenience, we expose the jQuery prototype as another global named, jQuery.fn. To make it truly chainable, the init function must return a new jQuery instance. Which is why, at the end, we explicitly define that the prototypes for both jQuery and jQuery.init are the same. This way, you can now chain function calls like

$(document).ready(DoSomethingHere)

Hope this helps.

Also, you can find the jQuery source on github. It's modular and quite easy to follow.

Share:
10,064
Jace Cotton
Author by

Jace Cotton

Web developer, designer, and 3D visualization artist. Based in Houston, TX.

Updated on July 05, 2022

Comments

  • Jace Cotton
    Jace Cotton almost 2 years

    How would jQuery allow its constructor to act as a function accepting arguments meanwhile its constructor also acts as a function accepting arguments?

    I am a bit new to JavaScript, so excuse me if this is a noob question, (I have looked at the source but it's hard to try to dissect).

    Anyway, as an example $(document).ready(<args>); Both the constructor $() and the prototype ready() act as a function. How? Because if I try this:

    var $ = function( selector ) {
        if(selector == document) {
            return document;
        }
    };
    
    $.prototype = {
        constructor: $,
        ready: function( args ) {
            if( isDomReady ) {
                args.apply( document );
            } else {
                window.onload = args;
            }
        }
    };
    
    var isDomReady = ( document.addEventListener || document.readyState == ("complete"|"loaded"|true|4) || document.onreadystatechange() ) ? true : false;
    
    $(document).ready(function() { alert("Wibbles!") });
    

    I get an error Uncaught TypeError: Object[object global] has no method 'ready'

  • Jace Cotton
    Jace Cotton about 11 years
    Ahh, okay. Thanks for the reference!
  • Jace Cotton
    Jace Cotton about 11 years
    Thank you! This is more of the direction I was looking for, but it came a little late, I already got into function chaining. Thanks, though!