Creating a jQuery like "$" object

As I write this, Squeegy's answer has the highest number of votes: 7. Yet it is wrong because __proto__ is non-standard and is not supported by Internet Explorer (even version 8). However, getting rid of __proto__ does not get it working either in IE 6.

This (somewhat simplified) is the way jQuery actually does it (even try it on IE 6), and it also includes examples of static methods and method chaining. For all the details of how jQuery does it, of course, you will have to check the jQuery source code yourself.

var MyClass = function(context) {
    // Call the constructor
    return new MyClass.init(context);
};

// Static methods
MyClass.init = function(context) {
    // Save the context
    this.context = context;
};
MyClass.messageBox = function(str) {
    alert(str);
};


// Instance methods
MyClass.init.prototype.print = function() {
    return "Printing";
};
MyClass.init.prototype.move = function() {
    return this.context;
};

// Method chaining example
MyClass.init.prototype.flash = function() {
    document.body.style.backgroundColor = '#ffc';
    setInterval(function() {
        document.body.style.backgroundColor = '';
    }, 5000);
    return this;
};


$('#output').append('<li>print(): '+ MyClass().print() +'</li>');
$('#output').append('<li>flash().move():'+ MyClass('azerty').flash().move() +'</li>');
$('#output').append('<li>context: '+ MyClass('azerty').context +'</li>');
MyClass.messageBox('Hello, world!');

Note that if you need "private" data, you will have to put instance methods inside MyClass.init (with a variable declared just inside that function) as this.print = function() { ... }; instead of using MyClass.init.prototype.


jQuery() is both a module with global methods, and a constructor. It automatically calls a constructor if it needs to. If we are not called with a new keyword, then this will not have been constructed with MyClass. We can detect that and call the function in constructor mode instead. Once we do that, then this will be an instance of MyClass and we can start adding stuff to it.

var MyClass = function(context) {
    // if the function is called without being called as a constructor,
    // then call as a constructor for us.
    if (this.__proto__.constructor !== MyClass) {
        return new MyClass(context);
    }

    // Save the context
    this.context = context;

    // methods...
    this.print = function() {
        return "Printing";
    }

    this.move = function() {
        return this.context;
    }
};

$('#output').append('<li>print(): '+ MyClass().print() +'</li>');
$('#output').append('<li>move():'+ MyClass('azerty').move() +'</li>');
$('#output').append('<li>context: '+ MyClass('azerty').context +'</li>');

http://jsfiddle.net/rvvBr/1/