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.