Переопределение методов в Javascript

Я хотел бы знать, в чем разница между переопределением методов с прототипами и без прототипов. Подумайте:

Пример 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 ответов


в первом методе каждый из Animal экземпляр получит свою собственную реализацию sleep и eat методы.

в то время как во второй модели все экземпляры будут иметь один и тот же экземпляр sleep и eat методы.

вторая модель лучше, так как мы можем поделиться методами.


как упоминал Арун в первом примере, который вы создаете sleep и eat функции для каждого нового экземпляра. Во втором примере есть только один sleep и eat функция, которая является общей для всех экземпляров.

в этом случае второй метод лучше, но хорошо знать, когда использовать первый метод и когда использовать второй. Сначала немного теории:

Примечание: в JavaScript есть четыре типа переменных - private, public, shared и static.

частные переменные недоступны вне функции, в которой они определены. Например:

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


в вашем первом примере каждый новый Dog экземпляр будет иметь свой собственный eat способ и во втором примере будет только один eat метод on Dog.prototype, который будет разделен между всеми будущими экземплярами Dog Как Арун говорил.

это только "хитрый" разница между этими двумя. Но всегда лучше определять методы на prototype для избежания высоких потребления и утечек памяти.


методы в первом примере определяются в экземпляре объекта.

настройки Dog прототип нового Animal например, таким образом Dog наследование sleep и eat функции Animal. Тогда ты определение (не переопределение) eat метод Dog конструктор как метод экземпляра, и это скрыть унаследовала eat метод Dog экземпляров.

рассмотреть следующий пример:

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

код выше будет предупреждать animal eating С вашим кодом в первом примере.

и уведомления Dog eating С кодом во втором.