在Javascript中覆盖方法

时间:2013-03-19 10:44:37

标签: javascript prototype method-overriding

我想知道重写方法与原型和没有原型之间的区别。考虑:

示例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();

示例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();

我觉得这两个例子产生的效果与Dog类覆盖Animal类的eat方法相同。或者有什么不同的事情发生?

4 个答案:

答案 0 :(得分:10)

在第一种方法中,每个Animal实例都会获得自己的sleepeat方法实现。

在第二个模型中,所有实例将共享sleepeat方法的相同实例。

第二种模式更好,因为我们可以分享方法。

答案 1 :(得分:6)

正如Arun在第一个示例中提到的那样,您为每个新实例创建了sleepeat函数。在第二个示例中,只有一个sleepeat函数在所有实例之间共享。

在这种情况下,第二种方法更好,但最好知道何时使用第一种方法以及何时使用第二种方法。首先是一点理论:

注意: JavaScript中有四种变量 - privatepublicsharedstatic

私有变量在定义它们的函数之外是不可访问的。例如:

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

公共变量在函数内的this对象上定义。例如:

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

共享变量在函数的prototype上共享。例如:

function f() {}

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

静态变量是函数本身的属性。例如:

function f() {}

f.x; // this is a static variable

大多数情况下,最好将构造函数的方法声明为共享方法,因为构造函数的所有实例都共享它们。但是,如果您的方法需要访问私有变量,则必须将其声明为公共方法本身。

注意:这是我自己的命名法。没有多少JavaScript程序员遵守它。其他人似乎遵循道格拉斯·克罗克福德的命名法:http://javascript.crockford.com/private.html

要了解有关JavaScript中原型继承的更多信息,请阅读以下答案:https://stackoverflow.com/a/8096017/783743

答案 2 :(得分:0)

在您的第一个示例中,每个新的Dog实例都有自己的eat方法,在第二个示例中,eat上只有一个Dog.prototype方法,在Arun所提及的所有Dog实例之间共享。

这是这两者之间唯一的“棘手”差异。但是在prototype上定义方法总是更好,以避免高内存消耗和泄漏。

答案 3 :(得分:0)

第一个示例中的方法在对象实例中定义。

您正在将Dog原型设置为新的Animal实例,因此Dog将从sleep继承eatAnimal个函数。然后你在eat构造函数中定义(不是 OVERRIDING Dog方法作为实例方法,这将 HIDE eat个实例中的继承Dog方法。

考虑以下示例:

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

上面的代码会在第一个示例中使用您的代码提醒animal eating

并使用第二个代码提醒Dog eating