Inheritence in Javascript

I get a strange bug when I implement inheritence in Javascript using prototypes. I am wondering if someone can explain this. In the following code, I am trying to derive a child class from a parent class:

            parent_class=function(byref)
            {   
                if( !parent_class.prototype._vtbl )
                {
                        parent_class.prototype.parent_func= function(o) { return alert("parent_func"); }
                        parent_class.prototype._vtbl = true;
                }
            }



            child=function(byref)
            {
                parent_class.call(this,byref);

                if( !child.prototype._vtbl )
                {
                        child.prototype = new parent_class;
                        child.prototype.child_func      = parent_class.prototype.parent_func;

                        child.prototype._vtbl = true;
                }

            }


            function dotest()
            {
                var pub = new child;
                alert( pub.child_func );

                var pub2    = new child;
                alert( pub2.child_func );
            }

            dotest();

When you run the test in a browser (Firefox or IE), you get two alerts. The first one says that pub.child_func is undefined, the second one says that the pub.child_func is a valid function and is parent_class.parent_func. Why do you see this behavior. Is this a bug?

Answers:

Answer

Order of execution in javascript of such construct:

function SomeClass () { body(); }
var x = new SomeClass();

is this:

  1. new object which inherits from SomeClass.prototype is created (the prototype for the object is chosen here, before code of the constructor is executed)
  2. body(); gets executed
  3. created object is assigned to x

What you can do in your example is use .__proto__, although you really really should not:

child = function (byref) {
    parent_class.call(this, byref);
    if (!child.prototype._vtbl) {
        child.prototype = new parent_class;
        child.prototype.child_func = parent_class.prototype.parent_func;
        child.prototype._vtbl = true;
    }
    this.__proto__ = child.prototype;
}

What you really should do is this:

child = function (byref) {
    parent_class.call(this, byref);
}
child.prototype = Object.create(parent_class.prototype);
child.prototype.child_func = parent_class.prototype.parent_func;
child.prototype._vtbl = true;
Answer

An easier way to do JavaScript inheritance might be the factory pattern:

function Animal(name) {
    return {
        run: function() {
          alert(name + " is running!")
        }
    }
}

var animal = Animal("fox");
animal.run();

function Rabbit(name) {
  var rabbit = Animal(name);

  rabbit.bounce = function() {
    this.run();
    console.log(name + " bounces");
  }

  return rabbit;
}

var rabbit = Rabbit("rabbit");
rabbit.bounce();

Source: http://javascript.info/tutorial/factory-constructor-pattern

Answer

Short answer: No, it's not browser mistake, it's expected behavior.

Detailed answer: When a constructor function is called with new, reference to it's prototype is copied into objects's __proto__. Later on this property is used for prototypal lookups for this object.
Your code is really weird from point of view of javascript developer, when you modify prototype of constructor during constructor call execution. However, it works. Because, after var parent = new parent_class(); the following is true parent.__proto__ === parent_class.prototype. It is the SAME reference. Thus adding properties to parent_class.prototype is automatically relfected in parent object via prototypal lookup. Unfortunately I can't post comments yet, so I have to reference from my answer, @RyszardFi?ski it is not a correct statement that prototype is defined before contructor called and can't be changed afterwards. It is the same object and unless you change the reference changes will be reflected immediately for all instantiated objects

However in child code in OP ruins references when child.prototype is assigned to a new object.

child.prototype = new parent_class;

child.prototype start pointing a to new instance of parent_class (#1). Instance references look like below

pub.__proto__ === child.prototype
pub2.__proto__ === parentInstance1
child.prototype === parentInstance2

If you remove the line of code where child.prototype is assigned everything will start working as you expect it

pub.__proto__ === child.prototype
pub2.__proto__ === child.prototype
child.prototype === child.prototype
child.prototype has properties _vtbl and child_func

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.