Inheritence in Javascript

拜拜、爱过 提交于 2020-01-25 09:01:29

问题


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?


回答1:


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;



回答2:


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




回答3:


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


来源:https://stackoverflow.com/questions/31100648/javascript-prototypal-inheritance-and-new-keyword

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!