0

UPDATE

Since I made this question, a lot of water has gone under the river, I have switch to use module pattern and CommonJS file format + Browserify and stop trying to make Javascript be more like an OOP language. I have embraced the Javascript Prototypal Inheritance and Object.create and I my life is now better than ever!, yes almost feeling like I joined a new Religion, sorry a religion... no "new" for me anymore in JS.

The rest of the question is just history...


I have being playing around with OOP for a while in javascript.

Honestly the feeling I have is that most of the time true OOP is not needed. What I was used to do in other languages with OOP, could be done with functions and closures in javascript most of the time.

Also to mimic the OOP approach there are tons of ways to enable it either making it by hand or using a tiny library found out there.

I wanted to give it a try to OOP but all the solutions I found, seemed to me no that simple, some requesting me to add a init method or during initialization they were doing special inspection of the the functions to know if they need to be override. While that is clever it seemed a bit excessive for simple creating an object from a Class.

So I came with this solution:

UPDATE: this an experiment, not intended to replace any brilliant exiting library or to be used in production

var Nexus = function() {}; // helper function to avoid create an instance of the child class
Object._extend = function(child, parent) {

  var base = Nexus.prototype = parent.prototype;
  child.prototype = new Nexus();

  var cp = child.prototype;
  cp.constructor = child;
  child._parent = base;
};




/* THIS THEN IS USED LIKE THIS */

var Person = function (name) {
  this.name = name;
  console.log('Person constructor');
};

$.extend(Person.prototype, {
  walk : function () {
    console.log(this.name + ' is Walking!!');
  }

});

var Student = function () {
  // call the base class constructor
  Student._parent.constructor.apply(this, arguments);
  console.log('Student Constructor');
}

Object._extend(Student, Person);

$.extend(Student.prototype, {
  walk : function () {
    console.log(this.name + ' walks like Student');
    //calling a parent method
    Student._parent.walk.apply(this, arguments);
  }
});

var p = new Person('Jon Doe');
p.walk();
console.log(p instanceof Person) // true

var s = new Student('Joan Doe');
s.walk();
console.log(s instanceof Person) // true
console.log(s instanceof Student) // true

As you can see, this approach fulfills what the OOP requires.

  1. A Child obj is an instance of a Parent Class too as well as the instance of the child class
  2. A Child obj can call the methods of the parent class to access overridden methods. (The only difference from CurrentClass._parent and BaseClass.prototype is that the second one requires the consumer of the class to actually know the name of the parent class, which I wanted to avoid).

  3. Creating a constructor had to be simple, in this case... the function itself is the constructor. No need of simple init methods... that are auto called during instantiation.

The cons in the approach I followed:

  1. I need a dummy class Nexus (I don't really like to instantiate an object of the base class only to get the inheritance chain to work properly... Nexus does the trick)
  2. I didn't provide access to the overridden methods with the context properly set. It is up to the consumer to change the context using either call or apply.

Does having the extra Nexus dummy function to create the right prototype chain is an issue for memory management?

I haven't had time to make proper tests, and my inheritance chains are not deeper than 3 levels. So the impact there seems to be very tiny.

I could have being using a library for that, but It seemed extremely simple to make it directly and still put some code in the constructors that I fail to see the benefits from having an extra init class for initialization.

What do you think will adding the dummy Nexus function have any noticeable impact?

roy riojas
  • 2,406
  • 1
  • 28
  • 30
  • 1
    In my opinion, your intuitive feelings that OOP for JavaScript is somewhat inappropriate are correct. – Pointy Feb 21 '13 at 22:27
  • Yep I did that more as an experiment than for real use. That's why I'm asking. Thanks for your feedback – roy riojas Feb 21 '13 at 22:29
  • @Point and OP Thank you! Finally some one who won't agrue that JavaScript is OOP, because it isn't, it's just playing with scope. If you need to hide data just use a Module Pattern, don't go crazy! – Iron3eagle Feb 21 '13 at 22:30
  • 1
    @royriojas, A lot of existing libraries do similar things to this. There's no need to roll your own. – Mike Samuel Feb 21 '13 at 22:30
  • 2
    What exactly is the question? "What do you think" is [not the kind of questions to be asked here](http://stackoverflow.com/faq#dontask) – Bergi Feb 21 '13 at 22:31
  • @MikeSamuel I think we need no OOP in the first place. I did it more as an experiment. And because is fun. When Chrome first appeared there were other good browsers like Firefox, then they came, I found the argument that don't make something new just because there are other thing similar out there a bit preventing innovation... And furthermore. This is just an experiment... My main question here is, do that tiny Nexus function will be an issue?. Thanks for the feedback – roy riojas Feb 21 '13 at 22:33
  • What do you mean with your Con #2? The overridden method `Person.prototype.walk` is quite accessible from everywhere – Bergi Feb 21 '13 at 22:33
  • @Bergi What do you think will adding the dummy Nexus function have any noticeable impact? Updated the question. Sorry for the ambiguos question. – roy riojas Feb 21 '13 at 22:35
  • @Bergi not if Person is not in the public scope but in private scope – roy riojas Feb 21 '13 at 22:36
  • @royriojas: Of course local variables are not accessible from anywhere. Yet everyone with access to a Person instance can get the function, for example even `Object.getPrototypeOf(studentInstance).walk` – Bergi Feb 21 '13 at 22:41

1 Answers1

2

Does having the extra Nexus dummy function to create the right prototype chain is an issue for memory management?

No. You've just got an (one!) additional object floating around in memory. Move it into the Object._extend function and it even will automatically garbage-collected.

However, instead of that Nexus thing you should just use Object.create. See also Understanding Crockford's Object.create shim.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks for the feedback, and definitively will give a try to Object.create shim – roy riojas Feb 21 '13 at 22:42
  • For experiments you won't need to shim it :-) Just linked that to help understanding why your code worked as well. See also http://stackoverflow.com/q/4166616/1048572 and http://stackoverflow.com/q/2709612/1048572 – Bergi Feb 21 '13 at 22:45
  • Does the object.create just create a new object right? so it is not really like creating a new Object from a predefined class. It is fine in any case as I say hardly I need more than 3 levels of inheritance. – roy riojas Feb 21 '13 at 22:52