Подтвердить что ты не робот

Настройка методов через прототип объекта или в конструкторе, разница?

Не могли бы вы объяснить разницу между методами установки в конструкторе и прототипом объекта? В следующем коде показаны два способа установки методов: say_hello и say_bye работают нормально:

function MessageClass() {
  this.say_bye = function() { alert('see ya'); };
}

MessageClass.prototype.say_hello = function() { alert('hello'); };

x = new MessageClass();
x.say_hello();
x.say_bye();
4b9b3361

Ответ 1

foxxtrot и annakata оба правильны, но я брошу свои 2 цента.

Если вы используете прототип, то каждый экземпляр "MessageClass" действительно ссылается на одни и те же функции. Функции существуют в памяти только один раз и используются для всех экземпляров. Если вы объявляете методы в конструкторе (или иным образом добавляете его в конкретный экземпляр), а не в прототип, то для каждого экземпляра MessageClass создается новая функция.

В большинстве случаев, вероятно, нет заметных различий в производительности, и маловероятно, что вы также увидите разницу в использовании памяти. Я бы пошел с прототипом, если у вас нет веских оснований для этого. Единственная причина, по которой я могу сказать, что вы хотите объявить метод в конструкторе, - это то, что вам нужно закрыть. Например, если у вас есть обработчики событий или вы хотите имитировать частные свойства с помощью getters/seters, вы можете сделать:

function MessageClass() {
    var self = this;
    this.clickHander = function(e) { self.someoneClickedMe = true; };

    var _private = 0;
    this.getPrivate = function() { return _private; };
    this.setPrivate = function(val) { _private = val; };
}

РЕДАКТИРОВАТЬ:. Поскольку обсуждалось, как эти объекты эффектов распространяются другим объектом с функциями, назначенными в конструкторе, я добавляю немного более подробно. Я мог бы использовать термин "класс" для упрощения обсуждения, но важно отметить, что js не поддерживает классы (это не значит, что мы не можем делать хорошую разработку OO), или мы не будем обсуждать эту проблему.

Большинство javascript-библиотек вызывают конструктор в базовом классе и подклассе. (например, Prototype.js Object.extend) Это означает, что методы, назначенные в конструкторе каждого из них, будут доступны на результирующих объектах. Однако, если вы распространяете объекты самостоятельно, могут возникнуть непредвиденные последствия.

Если я возьму MessageClass выше и расширю его:

function ErrorMessageClass() {}
ErrorMessageClass.prototype = new MessageClass();

errorMsg = new ErrorMessageClass();

Тогда errorMsg будет иметь метод getPrivate и setPrivate, но они могут не вести себя так, как вы ожидали. Поскольку эти функции были ограничены, когда они были назначены (т.е. В "ErrorMessageClass.prototype = new MessageClass()" не только доступны методы get/setPrivate, переменная _private получает общий доступ ко всем экземплярам ErrorMessageClass. Это, по сути, делает _private static свойство для ErrorMessageClass. Например:

var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'A'
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'B'

Аналогично с функцией clickHandler и свойством someoneClickedMe:

errorA.clickHandler();
console.log(errorA.someoneClickedMe); // prints 'true'
console.log(errorB.someoneClickedMe); // prints 'true'

Однако измените эти определения функций, чтобы использовать this._private:

this.getPrivate = function() { return this._private; };
this.setPrivate = function(val) { this._private = val; };

и поведение экземпляров ErrorMessageClass становится больше того, что вы ожидаете:

errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'B'

Ответ 2

Если вы связываете методы прототипом, JS должен сделать это один раз и привязывается к классу объектов (что делает его доступным для расширений OO JS).

Если вы выполняете привязку в функции класса, JS должен выполнять работу по созданию и назначению для каждого экземпляра.

Ответ 3

Разница заключается в том, что вы получаете класс из класса сообщений. Только класс, объявленный в прототипе, будет доступен в дочерних классах Message.