The jQuery constructor sort of maps its functionality to another
constructor
The fact is that jQuery is not really a constructor function and shouldn't be seen as one either. By definition, a constructor's responsability is to initialize instance properties, which is not really the case with jQuery. Also, calling new jQuery() would be non-sense. jQuery is a factory function for creating jQuery.fn.init instances, nothing more.
Now, perhaps you are wondering why they simply didin't use jQuery as a real constructor?
Well because they did not want a constructor that we call with new all the time, they wanted a factory function. That's fine with me, however where I tend to disagree is that their pattern is very cryptic and doesn't quite reflect the intention.
It would have been far better in my opinion to chose better names:
function jQuery(selector, context) {
return new jQuery.Set(selector, context);
}
jQuery.Set = function (selector, context) {
//constructor logic
};
//allows syntaxic sugar
jQuery.fn = jQuery.Set.prototype = {
constructor: jQuery.Set,
//methods
};
I've pretty much only remapped jQuery.fn.init to jQuery.Set and it suddenly all makes more sense to me. When looking at the code above, it's easy to see that:
jQuery is a factory function for creating jQuery.Set objects.
jQuery.fn exists only as a syntaxic sugar, instead of having to write jQuery.Set.prototype all the time to modify the prototype.
Now, in the source we also see that they do the following, which is kinda non-sense since jQuery is not the real constructor, it's jQuery.prototype.init and since we aren't creating jQuery instances, setting jQuery.prototype seems useless:
jQuery.fn = jQuery.prototype = {
constructor: jQuery
One of the reasons behind this is certainly that they want to accomodate people that might modify jQuery.prototype instead of jQuery.fn.
However another valid reason is that they perhaps wanted somejQueryObj instanceof jQuery to returns true, while it normally wouldn't. If you take the pattern above (with jQuery.Set) you will notice that:
jQuery() instanceof jQuery; //false
jQuery() instanceof jQuery.Set; //true
However if we set the prototype of jQuery to jQuery.Set.prototype, let's see what happens.
jQuery.prototype = jQuery.Set.prototype;
jQuery() instanceof jQuery; //true!
It's not easy to understand eveything that led to those design decisions and perhaps I am missing important points, but to me it seems their design is overcomplicated.