Overriding methods in Javascript

2019-01-18 12:12发布

I would like to know what is the difference between overriding methods with prototypes and without prototypes. Consider:

Example 1:

function Animal() {
    this.sleep = function () {
        alert("animal sleeping");
    };

    this.eat = function () {
        alert("animal eating");
    };
}

function Dog() {
    this.eat = function () {
        alert("Dog eating");
    };
}

Dog.prototype = new Animal;

var dog = new Dog;

dog.eat();

Example 2:

function Animal() { }

function Dog() { }

Animal.prototype.sleep = function () {
    alert("animal sleeping");
};

Animal.prototype.eat = function () {
    alert("animal eating");
};

Dog.prototype = new Animal;

Dog.prototype.eat = function () {
    alert("Dog eating");
};

var dog = new Dog;

dog.eat();

I feel both examples produce the same effect that the Dog class is overriding the eat method of the Animal class. Or is there anything different happening?

4条回答
小情绪 Triste *
2楼-- · 2019-01-18 12:48

As Arun mentioned in the first example you're creating sleep and eat functions for each new instance. In the second example there's only one sleep and eat function which is shared amongst all the instances.

In this case the second method is better, but it's good to know when to use the first method and when to use the second. A little bit of theory first:

Note: There are four kinds of variables in JavaScript - private, public, shared and static.

Private variables are inaccessible outside of the function in which they are defined. For example:

function f() {
    var x; // this is a private variable
}

Public variables are defined on the this object inside a function. For example:

function f() {
    this.x; // this is a public variable
}

Shared variables are shared on the prototype of the function. For example:

function f() {}

f.prototype.x; // this is a shared variable

Static variables are properties of the function itself. For example:

function f() {}

f.x; // this is a static variable

Most often it's best to declare the methods of a constructor function as shared methods since all instances of the constructor share them. However if your method needs to access a private variable then it must be declared as a public method itself.

Note: This is my own nomenclature. Not many JavaScript programmers adhere to it. Others seem to follow Douglas Crockford's nomenclature: http://javascript.crockford.com/private.html

To know more about prototypal inheritance in JavaScript read the following answer: https://stackoverflow.com/a/8096017/783743

查看更多
混吃等死
3楼-- · 2019-01-18 12:50

In the first method each of the Animal instance will get its own implementation of sleep and eat methods.

While in the second model All instances will share the same instance of the sleep and eat methods.

The second model is better since we can share the methods.

查看更多
祖国的老花朵
4楼-- · 2019-01-18 12:57

In your first example each new Dog instance will have it's own eat method and in the second example there will be only one eat method on Dog.prototype, which will be shared between all future instances of Dog like Arun mentioned.

This is the only "tricky" difference between those two. But it's always better to define methods on the prototype to avoid high memory consumption and leaks.

查看更多
时光不老,我们不散
5楼-- · 2019-01-18 13:03

The methods in first example are defined in object instance.

You're setting the Dog prototype to a new Animal instance, thus Dog will inherit sleep and eat functions from Animal. Then you're DEFINING (NOT OVERRIDING) eat method in Dog constructor as an instance method, and this will HIDE the inherited eat method in Dog instances.

Consider the following example:

function LittleDog() { }
LittleDog.prototype = Object.create(Dog.prototype);
(new LittleDog()).eat();

The code above will alert animal eating with your code in first example.

And will alert Dog eating with the code in the second one.

查看更多
登录 后发表回答