Thursday, November 27, 2008

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.

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

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();

Extension is also simple. We just need to decorate its prototype like this

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();

The constructor is very tricky. First I need to create a jQuery object without "new" keyword. Can we just do this like the following?

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.

It works. But seemly, there is a serious bug, that it returns a singleton. So I want to write the following naive code.

var jQuery = function() { return new jQuery.prototype; //jQuery.prototype is not a constructor //return new jQuery.prototype(); //jQuery.prototype is not a constructor }

It says, jQuery.prototype is not a constructor. so we need a constructor function to do the job.

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

Now everything works. But there is a potential that user may 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 Create Advanced Web Applications With Object-Oriented Techniques more about the "new".

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

Can we make it more simple, yes, let's move the jQueryConstructor into the prototype.

var jQuery = function() { return new jQuery.fn.init(); } jQuery.fn = jQuery.prototype = { init: function() {}, version: "1.0", showVersion: function() { alert(this.version); return this; }, work: function() { alert("work"); return this; } } 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

Done. I have skeleton of jQuery.

No comments:

Post a Comment