My JavaScript book is out!
Don't miss the opportunity to upgrade your beginner or average dev skills.

Thursday, July 26, 2007

625 bytes to extend JavaScript

These days I've studied (again) JavaScript prototypal inheritance and common extend functions or methods used by different libraries.This post is a summary about my experiments and every example code is based on this script.

Probably someone is thinking about my unreadable source code, however it's self packed and quite clear, atleast for me.The goal was to write 2 basic prototypes to extend objects or functions using "best practices" to do them using less chars as possible ... so, goal done ;-)

If You're interested about these prototypes logic please tell me, I'll try to find more time to explain better each one.

Object.prototype.extendThis is the first proposal and it's really simple to use/understand.

var a = {a:"a"}, b = {b:"b"}.extend(a);alert([b.a, b.b]); // a,b

This is a basic example.Extend prototype works with object itself and return them after a for in loop discarding prototyped methods.

Obviously, extend prototype sets correctly toString and valueOf methods with IE too, what You just need to remember is that if extended objects have two methods with the same name, last one only will be available:

That's all, Object.prototype.extend is just what You need when You need to extend some object.Only a last note about extend, it should work with other variables type too but please remember that for in loop doesn't always respect assignment order:

var a = [,,,4,5,6].extend([1,2,3]);alert(a); // 1,2,3,4,5,6

This is "a case" and not a rule so please use concat native method to extend Arrays or test for in loops before You use them with variables that are not instances or native objects.

Function.prototype.extendThis is my second prototype proposal, partially based on first one but really more powerful.This prototype extends constructors and return them adding special features that other libraries don't use.

As first point, this prototype assigns correctly constructor used to create other one.This seems to be a "natural" behaviour but I'm sure that not every other library assign them correctly.The constructor property is not "secure" as instanceof check but first one could be easyly compared, for example, inside a swtich:

With more complex code this feature is not so unusual while instanceof requires a lot of if ... else if ... else.This property is useful for a lot of other pieces of code too, so why We shouldn't have a correct constructor property when We create or extend another one?

This is another example that has a "not everytime" respected behaviour (using other libraries):

If You think that a new C instance will not crash or block your browser You're wrong!Since apply or call methods inject temporary into another method (function) scope a different this referer, You should think about B.prototype.init one.This method will use a C instance as this referer but C instance will have its own properties and its own methods.Infact C instance will have a parent property too that will be exactely B constrcutor so above example, using a new C instance, will loop recursively calling as many times as it can B.prototype.init.

The solution is really simple, just use explicitally constrcutor as showed in this example:

Is it ok? Of course, it works perfectly.However other languages have a dedicated keyword to use constructor recoursively or not and this keyword should be parent or super one.In JavaScript the super keyword is reserved so it should be a good idea to don't use them if it's not absolutely necessary (used as string, for example), that's why I've created a Supermagic method and this is how does it work:

Simple? I hope them and this way to use inheritance is quite cool (imho) ;-)You don't need to care about constrcutor name and You don't need to use call or apply, just specify parent method name to call or, if You need to call super constructor, just use a nullable value such 0, "", undefined, false or null.