Определение методов прототипа внутри конструктора

Сегодня я увидел шаблон JavaScript, который никогда не видел за всю свою жизнь. Я не могу сказать цель использования этого шаблона. Мне это кажется неправильным, но я хочу быть немного консервативным. Это может быть какой-то удивительный узор, который я никогда раньше не видел.

function Dog() {
    Dog.prototype.bark = function () {
        alert('woof!');
    }

    this.bark = function () {
        Dog.prototype.bark();
    }

    this.bark();
}

Во-первых, я не сторонник создания методов (как привилегированных членов) внутри конструктора без всякой причины. Это вызовет создание функций каждый раз, когда создается экземпляр. Во-вторых, в этом фрагменте кода он также называет имя прототипа «Собака», а не «этот». Это меня очень смущает.

Кто-нибудь знает, что в нем хорошего?

Спасибо! Милость


person Grace Shao    schedule 19.08.2011    source источник
comment
Это кажется крайне бессмысленным. Насколько я знаю, объект-прототип используется для добавления свойств ко всем экземплярам объекта вне определения. Так как это в определении, это немного избыточно.   -  person mowwwalker    schedule 19.08.2011
comment
Я полностью согласен с тобой. Мне тоже это кажется бессмысленным.   -  person Grace Shao    schedule 19.08.2011


Ответы (2)


Это очень плохая идея по целому ряду причин. Вот некоторые из них:

  1. Добавление методов к прототипу в конструкторе приведет к замене метода прототипа для всех экземпляров каждый раз, когда вы создаете новый экземпляр Dog.
  2. Вызов Dog.prototype.bark() означает, что this будет Dog.prototype, а не вашим экземпляром Dog, что может вызвать серьезные проблемы.
  3. this.bark = function () { Dog.prototype.bark(); } это какой-то серьезный WTF. Потому что this.bark уже будет оценивать метод прототипа, что делает это ненужным. И такое обращение на самом деле уничтожает естественное значение this, как упоминалось в #2.

Вот что должно быть:

function Dog() {
  this.makeSound();
};

Dog.prototype.bark = function() {
  alert('woof');
};

Dog.prototype.makeSound = function() {
  this.bark();
};

Или, как вариант, вообще без прототипа:

function Dog() {
  this.bark = function() {
    alert('woof');
  };

  this.makeSound = function() {
    this.bark();
  };

  this.makeSound();
};

Я бы не стал доверять этому вашему фрагменту вообще.

person Alex Wayne    schedule 19.08.2011
comment
# 2: то же самое, даже если bark инициализируется вне конструктора - метод this устанавливается вызовом. #3: то же, что и #2 (this будет Dog.prototype), но функция не использует this, поэтому она не будет вызвать проблему в этом случае. - person RobG; 19.08.2011
comment
Зачем тебе делать this.makeSound = function() { }? Этот пример может ввести в заблуждение без пояснений. Это не устанавливается для объекта-прототипа, и функция дублируется в памяти для каждого экземпляра new Dog();. Лучше Dog.prototype.makeSound = function () {} - person dman; 07.09.2016

Извините за ОЧЕНЬ поздний ответ, но если вы действительно хотите добавить прототипы в конструктор и не создавать его заново при создании нового экземпляра, вы можете сделать это:

function Dog() {
    if (!Dog.prototype.bark) {
        Dog.prototype = function() {
            console.log('woof');
        }
    }

    this.bark();
}

Я все еще, вероятно, не стал бы использовать этот метод, но у меня есть несколько случаев, когда этот метод был вариантом при работе со сторонними фреймворками (хитрый вид).

person DrunkenBeetle    schedule 31.08.2015