Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is John Resig's OO JavaScript implementation production safe?

Tags:

For a long time I have been throwing around the idea of making my JavaScript more object oriented. I have looked at a few different implementations of this as well but I just cannot decide if it is necessary or not.

What I am trying to answer are the following questions

  • Is John Resig's simple inheritance structure safe to use for production?
  • Is there any way to be able to tell how well it has been tested?
  • Besides Joose what other choices do I have for this purpose? I need one that is easy to use, fast, and robust. It also needs to be compatible with jQuery.
like image 933
Metropolis Avatar asked Sep 28 '10 22:09

Metropolis


1 Answers

Huh. It looks much more complicated than it needs to be, to me.

Actually looking more closely I really take exception to what it is doing with providing this._super() whilst in a method, to call the superclass method.

The code introduces a reliance on typeof==='function' (unreliable for some objects), Function#toString (argh, function decomposition is also unreliable), and deciding whether to wrap based on whether you've used the sequence of bytes _super in the function body (even if you've only used it in a string. and if you try eg. this['_'+'super'] it'll fail).

And if you're storing properties on your function objects (eg MyClass.myFunction.SOME_PRIVATE_CONSTANT, which you might do to keep namespaces clean) the wrapping will stop you from getting at those properties. And if an exception is thrown in a method and caught in another method of the same object, _super will end up pointing at the wrong thing.

All this is just to make calling your superclass's method-of-the-same name easier. But I don't think that's especially hard to do in JS anyway. It's too clever for its own good, and in the process making the whole less reliable. (Oh, and arguments.callee isn't valid in Strict Mode, though that's not really his fault since that occurred after he posted it.)

Here's what I'm using for classes at the moment. I don't claim that this is the “best” JS class system, because there are loads of different ways of doing it and a bunch of different features you might want to add or not add. But it's very lightweight and aims at being ‘JavaScriptic’, if that's a word. (It isn't.)

Function.prototype.makeSubclass= function() {     function Class() {         if (!(this instanceof Class))             throw 'Constructor function requires new operator';         if ('_init' in this)             this._init.apply(this, arguments);     }     if (this!==Object) {         Function.prototype.makeSubclass.nonconstructor.prototype= this.prototype;         Class.prototype= new Function.prototype.makeSubclass.nonconstructor();     }     return Class; }; Function.prototype.makeSubclass.nonconstructor= function() {}; 

It provides:

  1. protection against accidental missing new. The alternative is to silently redirect X() to new X() so missing new works. It's a toss-up which is best; I went for explicit error so that one doesn't get used to writing without new and causing problems on other objects not defined like that. Either way is better than the unacceptable JS default of letting this. properties fall onto window and mysteriously going wrong later.

  2. an inheritable _init method, so you don't have to write a constructor-function that does nothing but call the superclass constructor function.

and that's really all.

Here's how you might use it to implement Resig's example:

var Person= Object.makeSubclass(); Person.prototype._init= function(isDancing) {     this.dancing= isDancing; }; Person.prototype.dance= function() {     return this.dancing; };  var Ninja = Person.makeSubclass(); Ninja.prototype._init= function() {     Person.prototype._init.call(this, false); }; Ninja.prototype.swingSword= function() {     return true; };  var p= new Person(true); p.dance(); // => true  var n = new Ninja(); n.dance(); // => false n.swingSword(); // => true  // Should all be true p instanceof Person && n instanceof Ninja && n instanceof Person 

Superclass-calling is done by specifically naming the method you want and calling it, a bit like in Python. You could add a _super member to the constructor function if you wanted to avoid naming Person again (so you'd say Ninja._super.prototype._init.call, or perhaps Ninja._base._init.call).

like image 72
bobince Avatar answered Sep 27 '22 21:09

bobince