Не могли бы вы объяснить разницу между методами установки в конструкторе и через объект-прототип? В следующем коде показаны эти два способа настройки методов - оба 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();



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Разница в том, когда вы наследуете класс от класса сообщений. В дочерних классах Message будут доступны только методы, объявленные в прототипе.
Я могу вызвать метод say_bye (который объявлен как this) из дочернего класса. Вот мой код: function Employee () {this.say_bye = function () {alert ('увидимся'); }; } function Manager () {} Manager.prototype = новый сотрудник; Manager.prototype.constructor = Менеджер; var manager = новый менеджер (); manager.say_bye ();
@foxxtrot Это неверно. Даже методы, объявленные в this внутри конструктора, доступны в дочернем классе. Рассмотрим код errorA.setPrivate('A') от Prestaul, который обращается к методу, объявленному на this родительским классом MessageClass.
Я также ошибочно думал, что разница заключается в наследовании, но это не так: function parentClass() { this.inheritedFunc = function() {return "Some Value"}; } function childClass() {}; childClass.prototype = new parentClass(); var childObj = new childClass(); console.info(childObj.inheritedFunc()); //successfully logs "Some Value"
Если вы привязываете методы по прототипу, JS нужно сделать это только один раз и привязать к классу объекта (что делает его понятным для расширений OO JS).
Если вы выполняете привязку в функции «класса», JS должен выполнять работу по созданию и назначению для каждого экземпляра.
Что, если я сначала определю методы как функции, а затем скажу в конструкторе следующее: 'this.say_bye = MessageClass_sayhello;
немного лучше, но все же не так эффективно, как прототипирование, и вы все еще не можете расширить это
Вопрос о возможности расширения объекта будет во многом зависеть от того, какую js lib вы используете и используете ли вы ее. Если конструктор вызывается при расширении объекта, методы доступны. Я считаю, что большинство основных библиотек вызывают конструктор при расширении.
Например, если я сам расширяю объект: Subclass.prototype = new Class (); тогда функции, назначенные в конструкторе класса, доступны в подклассе. Однако эти функции являются общими для экземпляров Subclass, что может привести к неожиданному поведению. Конечно, лучше их прототипировать.
foxxtrot и annakata оба правильные, но я добавлю свои 2 цента.
Если вы используете прототип, тогда каждый экземпляр «MessageClass» действительно ссылается на одни и те же функции. Функции существуют в памяти только один раз и используются для всех экземпляров. Если вы объявляете методы в конструкторе (или иным образом добавляете его к конкретному экземпляру), а не в прототипе, то для каждого экземпляра MessageClass создается новая функция.
При этом, вероятно, нет заметной разницы в производительности для большинства случаев, и маловероятно, что вы также увидите разницу в использовании памяти. Я бы выбрал метод прототипа, если у вас нет веских причин поступить иначе. Единственная причина, по которой я могу сказать, что вы можете захотеть объявить метод в конструкторе, - это если вам нужно закрытие. Например, если у вас есть обработчики событий или вы хотите смоделировать частные свойства с помощью геттеров / сеттеров, вы можете сделать:
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 не поддерживает классы (это не значит, что мы не можем делать хорошую объектно-ориентированную разработку), иначе мы не будем обсуждать этот вопрос.
Большинство библиотек javascript вызывают конструктор базового класса и подкласса. (например, Object.extend Prototype.js). Это означает, что методы, назначенные в конструкторе каждого из них, будут доступны для результирующих объектов. Однако если вы сами расширяете объекты, это может привести к неожиданным последствиям.
Если я возьму MessageClass выше и расширю его:
function ErrorMessageClass() {}
ErrorMessageClass.prototype = new MessageClass();
errorMsg = new ErrorMessageClass();
Тогда errorMsg будет иметь методы getPrivate и setPrivate, но они могут вести себя не так, как вы ожидаете. Поскольку область действия этих функций была ограничена, когда они были назначены (то есть в «ErrorMessageClass.prototype = new MessageClass ()», используются не только методы get / setPrivate, но и переменная _private также используется во всех экземплярах ErrorMessageClass. Это, по сути, делает _private статическое свойство для ErrorMessageClass. Например:
var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
console.info(errorA.getPrivate()); // prints 'A'
console.info(errorB.getPrivate()); // prints 'A'
errorB.setPrivate('B');
console.info(errorA.getPrivate()); // prints 'B'
Аналогично с функцией clickHandler и свойством SomeClickedMe:
errorA.clickHandler();
console.info(errorA.someoneClickedMe); // prints 'true'
console.info(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.info(errorA.getPrivate()); // prints 'A'
console.info(errorB.getPrivate()); // prints 'B'
блин за ваше красноречие :) (хотя я не согласен, заметной разницы нет)
Хотя, если вы используете this._private, переменная доступна извне.
(технически говоря, вы можете отслеживать с помощью отладчика в любом случае, если не во всех, JS-средах)
Значит, если бы у меня был BetterMessageClass.prototype = new MessageClass, унаследовал бы только say_hello?