jQuery mini
I am fasinated by the jQuery library. I do so much more with so less code. Here I try to mimic jQuery several features: chain operation, extentsion, constructor.
<p>
chain operation is pretty easy to mimic. We just need to add "return this;" to the end of a method. Here is my first try</p>
<pre data-sub="prettyprint:_"> var jQuery = function() { } jQuery.prototype = {
version: "1.0",
showVersion: function() {
alert(this.version);
return this;
},
work: function() {
alert("work");
return this;
}
} var j = new jQuery(); j.showVersion().work();
</pre>
<p>Extension is also simple. We just need to decorate its prototype like this</p>
<pre data-sub="prettyprint:_"> var jQuery = function() {
} jQuery.prototype = { version: “1.0”, showVersion: function() { alert(this.version); return this; }, work: function() { alert(“work”); return this; } } var j = new jQuery(); j.showVersion().work(); jQuery.prototype.sleep = function() { alert(“sleep”); return this; } j.sleep();
</pre>
<p>The constructor is very tricky. First I need to create a jQuery object without "new" keyword. Can we just
do this like the following?</p>
<pre data-sub="prettyprint:_">
var jQuery = function() {
return jQuery.prototype;
}
jQuery.prototype =
{
version: "1.0",
showVersion: function() {
alert(this.version);
return this;
},
work: function() {
alert("work");
return this;
}
}
var j = new jQuery();
j.showVersion().work(); //chain works
jQuery.prototype.sleep = function() {
alert("sleep");
return this;
}
j.sleep(); //extension works
j.version = "2.0";
j.showVersion();
jQuery().showVersion(); //we can create a jQuery object without new, but it show 2.0, it is a singleton.
</pre>
<p>It works. But seemly, there is a serious bug, that it returns a singleton. So I want to write the following naive code.</p>
<pre data-sub="prettyprint:_"> var jQuery = function() {
return new jQuery.prototype;
//jQuery.prototype is not a constructor
//return new jQuery.prototype();
//jQuery.prototype is not a constructor
}
</pre>
<p>It says, jQuery.prototype is not a constructor. so we need a constructor function to do the job.
</p>
<pre data-sub="prettyprint:_">
var jQuery = function() {
return new jQueryConstructor();
}
jQuery.prototype =
{
version: "1.0",
showVersion: function() {
alert(this.version);
return this;
},
work: function() {
alert("work");
return this;
}
}
function jQueryConstructor() {
};
jQueryConstructor.prototype = jQuery.prototype;
//end of library
//following is test code.
var j = new jQuery();
j.showVersion().work(); //chain works
jQuery.prototype.sleep = function() {
alert("sleep");
return this;
}
j.sleep(); //extension works
j.version = "2.0";
j.showVersion();
jQuery().showVersion(); //it shows 1.0, it is not a singleton
</pre>
<p>Now everything works. But what if user change the jQuery.prototype accidentally. let's add
a reference jQuery.fn = jQuery.prototype, so that user focus on jQuery.fn, and let jQuery.prototype off attention.
So I change the code like the following . Please note that the "return new jQueryConstructor()", you must use "new".
Without "new", the prototype "jQueryConstructor.prototype = jQuery.fn" has no use. Here is an artical <a href="http://msdn.microsoft.com/en-us/magazine/cc163419.aspx">
Create Advanced Web Applications With Object-Oriented Techniques</a> more about the "new".
</p>
<pre data-sub="prettyprint:_">
var jQuery = function() { return new jQueryConstructor(); }
jQuery.fn = jQuery.prototype = { version: “1.0”, showVersion: function() { alert(this.version); return this; }, work: function() { alert(“work”); return this; }
}
function jQueryConstructor() { };
//jQueryConstructor.prototype = jQuery.prototype; jQueryConstructor.prototype = jQuery.fn;
var j = new jQuery(); j.showVersion().work(); //chain works
jQuery.fn.sleep = function() { alert(“sleep”); return this; }
j.sleep(); //extension works
j.version = “2.0”; j.showVersion(); jQuery().showVersion(); //it shows 1.0, it is not a singleton
</pre>
<p>Can we make it more simple, yes, let's move the jQueryConstructor into the prototype.</p>
<pre data-sub="prettyprint:_"> var jQuery = function() {
return new jQuery.fn.init(); }
jQuery.fn = jQuery.prototype = { //nested init constructor inside //is just a hack init: function() {}, version: “1.0”, showVersion: function() { alert(this.version); return this; }, work: function() { alert(“work”); return this; }
} //if we do not nested init inside //it would be init.prototype = jQuery.prototype jQuery.fn.init.prototype = jQuery.fn;
var j = new jQuery(); j.showVersion().work(); //chain works
jQuery.fn.sleep = function() { alert(“sleep”); return this; }
j.sleep(); //extension works
j.version = “2.0”; j.showVersion(); jQuery().showVersion(); //it shows 1.0, it is not a singleton
</pre>
<p>Done. I have skeleton of jQuery.</p>