13

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

示例 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该类覆盖了该类的 eat 方法Animal。或者发生了什么不同的事情?

4

4 回答 4

11

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

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

第二个模型更好,因为我们可以共享方法。

于 2013-03-19T10:49:10.187 回答
10

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

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

注意: JavaScript 中有四种变量 - privatepublic和.sharedstatic

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

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

于 2013-03-19T11:03:36.837 回答
0

在您的第一个示例中,每个新Dog实例都有自己的eat方法,而在第二个示例中,只有一个eat方法 on Dog.prototype,它将在所有未来的实例之间共享,Dog例如 Arun 提到的。

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

于 2013-03-19T11:05:17.627 回答
0

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

您正在将Dog原型设置为一个新Animal实例,因此Dog将从. 然后你在构造函数中定义(NOT OVERRIDING)方法作为实例方法,这将隐藏实例中的继承方法。sleepeatAnimaleatDogeatDog

考虑以下示例:

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

animal eating上面的代码将在第一个示例中使用您的代码发出警报。

Dog eating并会在第二个代码中发出警报。

于 2013-03-19T11:18:47.987 回答