Ok, it’s called JSoo now ^^
Ok, so naming a library Prototype wasn't a wise choice, which I knew in advance but inocently thought it be harmless since I created this lib as plugable functionality. It safe to say, I was dead wrong about that... In other news... I renamed the library to JSoo as suggested by shadedecho, I really do hope I am safe on this name... *crosses fingers*.
Andrea Giammarchi from Web Reflection also made it clear to me that I didn't succeed in making clear in how JSoo differs from other Class constructing systems. So I better try harder now. First of all, some basics.
In JavaScript inheritance is arranged through prototypes, you basically attach a property hash to a function's prototype attribute.
var Properties = { // property hash method : function() { alert("foo"); } } var aClass = function(){} var instance = new aClass(); instance.method(); //-> foo
One can declare the properties hash directly to a function's prototype attribute, however I deliberatly didn't do that in the above example. In the above example it is also possible to stick the Properties hash to another function's prototype attribute if desired and this is the rudementary concept behind JSoo. It makes the defined property hash leading instead of linking to the prototype attribute of a function. So we kinda steer clear from the Classical OO concept and approach the Object.beget idea more. Lets continue using what we set in the above example.
Properties.method = function(){ alert("bar"); } instance.method(); //-> bar
By changing/overriding the method in the "Properties" hash, we also change the methods in the function's prototype attribute and thus all the instance of that function as well. Changing the methods on the function's prototype attribute also works, but you can see this as changing a property through a reference to "Properties". So by creating a seperate hash variable before assigning it to a prototype attribute, we basically have a method set to play around with without even touching any functions. This IS basic prototypical inheritance.
The next thing you want is a means to mix multiple property hashes into new hashes (multiple inheritance), a means to keep them out of the global scope and manage them more tightly, a means to call the methods from donor hashes in case you want to override a method on an instance, a means to call the original method with the same name but from donor1 and donor2. JSoo supplies those means.
JSoo("Observer",{ observe : function(){ /* do stuff */ }, stopObserving : function() { /* do stuff */ }, fire : function() { /* do stuff */ } }); JSoo("Connector",{ load : function() { /* do stuff */ }, send : function() { /* do stuff */ } }); JSoo("ListLoader",{ load : function(url) { this.fire("loading", {message:"Loading the list"}); this["::Connector"].load.call(this, url); }, observe : function() { this.fire("observe", {message:"I am being watched!"}); this["::Observer"].observe.apply(this,arguments); } }, "Observer", "Connector"); var CityList = function(){ /* do stuff */ } CityList.prototype = JSoo("ListLoader");
The above example is just to give you an idea what you can do with JSoo.
JSoo supplies multiple inheritance through augmentation without having to search the scope chain since donor references are directly tied to the this keyword and prefixed with "::" to force a writing style to make you think twice on what you're doing as opposed to this.$super, which is pretty linear to begin with. You also don't have to assign a constructor or initializer when storing a property hash, some like that, some don't, imo. method sets (property hashes) should be portable and abstract, reducing reliance on constructors as much as possible, working more through arguments.
I will do a proper explanation on the JSoo.Module function in another installment.
So I reinvented prototype.js…
** EDIT, Library name is now JSoo, leaving this post intact to remind me of my stupid name choice for a library **
No, I am not talking about prototype.js from prototypejs.org I've actually created a prototypical Prototype Multiple Inheritance System and Module Pattern decorator library. Considering what the library does, I found Prototype was the best name for it and my appologies in advance to the prototypejs crew for naming it likewise. I also have to add, this is merely a working draft version and imo. good enough to release, namespace issues will be a later concern (though I am using a special namespace pattern for plug and play action
)
As a reaction to the Javascript Inheritance Performance post on Ajaxian, I found myself thinking; "Why is everyone trying to superimpose Classical OO on Prototypical OO" and "There should be a better way according to what Douglas Crockford tries to teach us through his articles and book". So I got to work and Prototype + Prototype.Module is my idea on how to handle inheritance in a nice and orderly way.
Other inheritance systems solve it function.prototype = {} >here<.
This inheritance system solves it >here< function.prototype = {}
A complete description of Prototype & Prototype.Module can be found here. *EDIT LINK CHANGED*
The library can be downloaded to play around with here. *EDIT LINK CHANGED*
A quick example to entice and show what the library does.
Prototype example:
The Prototype function basically leaves the functions alone and only handles property hashes, so we can assign them to functions AFTER they're properly defined. It also supports multiple inheritance the prototypical way and allows back references to donor property hashes.
Prototype("MammaCat", {
talk: function() {
return this.name + " says: miauw";
}
});
var MammaCat = function(name) {
this.name = name;
}
MammaCat.prototype = Prototype("MammaCat");
var Pookie = new MammaCat("Pookie");
alert(Pookie.talk()) //==> Pookie says: miauw
Prototype("Kitten", {
talk: function() {
return this.name + " says: meep";
},
myMommaSays: function() {
return "my momma " + this["::MammaCat"].talk.apply(Pookie);
}
}, "MammaCat"); // <-- Inherit methods from Cat.
var Kitten = function(name) {
this.name = name;
}
Kitten.prototype = Prototype("Kitten");
var Bella = new Kitten("Bella");
alert(Bella.talk()) //==> Bella says: meep
alert(Bella.myMommaSays()) //==> Pookie says: miauw
Prototype.Module example:
Prototype.Module provides a neat way to organise Module Patterns as well as allow the sharing of private variables over multiple Module Patterns through closure techniques.
Prototype.Module("combat", function(cache) {
cache.baseDamage = 10;
return {
rake: function() {
alert(this.name + " rakes for " + cache.baseDamage + " damage");
}
}
});
Prototype.Module("specialAttacks", function(cache) {
return {
claw: function() {
// yes, we reference a value set in another module pattern through the cache argument!
alert(this.name + " claws" + (cache.baseDamage + 10) + " damage");
}
}
});
// the cache argument in the module patterns gets shared as long as you assign the
// modules in a single call.
Prototype.Module.attach(Pookie, "combat", "specialAttacks");
Pookie.rake(); //==> Pookie rakes for 10 damage
Pookie.claw(); //==> Pookie claws for 20 damage
The code is at version 0.0.1 and is basically a first draft to show how inheritance can be solved the prototypical way. I do understand people want to make JavaScript look and behave more like Java, but it's simply not a classical OO language. Use and embrace the prototypical way of scripting!
I am sure people can find errors, performance issues and have better ideas or suggestions, feel free to post them and I will incorporate it, proper credits will be given
And if someone knows of a better name then Prototype (to avoid possible conflict with the good and nice lads at prototypejs.org), then I am very much open to suggestions.
The Namespace Pattern.
I'm constantly writing javascript libraries or writing new modules for other libraries (95% of which never sees daylight...) and I used to tie it all together with namespaces. I also used a lot of private variables within my libraries or modules, so I eventually thought to myself, why not do it all in one simple pattern everyone actually uses all the time already.
(function(ns){
ns = ns || window;
var myPrivate = "value";
var method = function(){ /* do stuff with private */ }
ns.method = method;
})(NameSpace); //<-- insert namespace here.
It basically keeps all my code portable and I never have any conflict issues. If for example John Resig's Sizzle was written this way, it would be dead simple to copy paste code and incorporate it within other libraries/framework. Ofcourse it takes little work to refactor a script to this purpose, but then you'd have to refactor it every single time someone released a new version and removing any eventuality of namespace assignments as well.
It's deadsimple, low level and not even complex enough to deserve a name, but I'll name it anyways: The Namespace Pattern.
\o/ @ first blogpost.