объявление методов в constructor и prototype
Я только начал изучать JS, и немного застрял. Все говорят что мы можем объявлять методы в прототипе, так как их легче переписать и они будут у всех созданных объектов. Но ведь мы можем так же объявить их в конструкторе, и они так же будут у всех объектов. Я понял что есть разница в использовании памяти, и что в прототипе метод создается только один раз. Но с практической точки зрения эти методы объявленные разным способом делают одно и тоже. В чем разница, и можете привести простой пример где лучше использовать prototype.
Ответы (2 шт):
Можно делать как угодно.
В конструкторе можно объекту надобавлять методов, и они будут работать ничуть не хуже прототипных. Раньше классов и конструкторов не было. Всё писалось просто в функции, которые начинали работать в особом режиме при операторе new, и многие использовали подход без прототипов вообще.
В этом подходе даже несколько плюсов есть. Например можно у одного объекта просто удалить какой-то метод потом. Или переписать какие-то методы - именно заменить, а не сделать второй поверх прототипного. Также при этом проще делается подмешивание поведения вместо наследования. То есть что-то вроде множественного наследования. Ещё был плюс в полноценных приватных переменных, которых нет до сих пор в классах, кроме теперешнего костыля с решёткой.
Такие объекты, как вы и сказали, потребляют больше ресурсов. Но на простых страничках обычно всё равно. И не такой уж страшный там расход, всё весьма легковесное.
Есть один важный нюанс. Обычно инструменты затачиваются под прототипный подход. И большинство js-программистов видимо его поддерживают. Так например в тайпскрипте вы не сможете пользоваться классами-функциями без прототипов, только полноценными классами. Иначе придётся городить какой-то тип вручную каждый раз, поверх уже написанной реализации.
Советую использовать прототипный подход, просто потому что под него всё заточено. И потому что при другом подходе очень легко залипнуть в "мне всё можно напихать в объект" и перестать понимать прототипы и бояться их потом.
Не первостепенной важности момент, и может быть делом вкуса, но нужно ещё учитывать читабельность кода. В нотации классов конструктор станет путаным и перегруженным, если сгрузить туда все методы. Сравните:
class Foo {
constructor(foo) {
this.foo = foo;
}
bar() {
console.log('bar');
}
baz() {
console.log('baz');
}
}
class Foo {
constructor(foo) {
this.foo = foo;
this.bar = function bar() {
console.log('bar');
};
this.baz = function baz() {
console.log('baz');
};
}
}
А если вы начнёте присваивать методы вне конструктора, начнутся уже существенные потери. Сейчас, например, вы потеряете возможность использовать приватные поля, которые могут быть только внутри декларации класса. И раз уж есть такой прецедент, дальше этот список ограничений может расти.