it-swarm.com.ru

Переопределение методов в 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. Или происходит что-то другое?

11
codingsplash

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

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

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

10
Arun P Johny

Как сказал Арун в первом примере, вы создаете функции 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

6
Aadit M Shah

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

Вы устанавливаете прототип 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 с кодом во втором.

0
fardjad

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

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

0
happyCoda