Я не думаю, что логика конструктора / фабрики вообще необходима, пока вы меняете свое отношение к объектно-ориентированному программированию.В моем недавнем исследовании этой темы я обнаружил, что прототипическое наследование больше подходит для определения набора функций, которые используют конкретные данные.Это не чуждое понятие для тех, кто обучается классическому наследованию, но загвоздка в том, что эти «родительские» объекты не определяют данные, с которыми нужно работать.
var animal = {
walk: function()
{
var i = 0,
s = '';
for (; i < this.legs; i++)
{
s += 'step ';
}
console.log(s);
},
speak: function()
{
console.log(this.favoriteWord);
}
}
var myLion = Object.create(animal);
myLion.legs = 4;
myLion.favoriteWord = 'woof';
Итак, в приведенном выше примеремы создаем функциональность, которая сопровождает животное, а затем создаем объект, обладающий этой функциональностью, вместе с данными, необходимыми для выполнения действий.Это неудобно и странно для любого, кто привык к классическому наследованию в течение любого отрезка времени.В ней нет ни одной из теплых размытостей публичной / частной / защищенной иерархии видимости членов, и я буду первым, кто признает, что заставляет меня нервничать.
Кроме того, мой первый инстинкт, когда я вижуПриведенная выше инициализация объекта myLion
заключается в создании фабрики для животных, чтобы я мог создавать львов, тигров и медведей (о мой) простым вызовом функции.И, я думаю, для большинства программистов это естественный способ мышления - многословность приведенного выше кода безобразна и, похоже, лишена элегантности.Я не решил, является ли это просто классическим обучением, или это фактическая ошибка вышеуказанного метода.
Теперь о наследовании.
Я всегда понимал наследование в JavaScript, чтобыбыть труднымНавигация по входам и выходам цепочки прототипов не совсем понятна.Пока вы не используете его с Object.create
, что исключает перенаправление всех ключевых слов на основе функций из уравнения.
Скажем, мы хотели расширить вышеуказанный объект animal
и сделать человека.
var human = Object.create(animal)
human.think = function()
{
console.log('Hmmmm...');
}
var myHuman = Object.create(human);
myHuman.legs = 2;
myHuman.favoriteWord = 'Hello';
Это создает объект, имеющий human
в качестве прототипа, который, в свою очередь, имеет animal
в качестве прототипа.Достаточно просто.Нет неправильного направления, нет «нового объекта с прототипом, равным прототипу функции».Просто простое наследование прототипа.Это просто и понятно.Полиморфизм тоже прост.
human.speak = function()
{
console.log(this.favoriteWord + ', dudes');
}
Из-за того, как работает цепочка прототипов, myHuman.speak
будет найден в human
, прежде чем он найден в animal
, и поэтому наш человек вместо этого является серферомпросто скучного старого животного.
Итак, в заключение ( TLDR ):
Функциональность псевдоклассического конструктора была отчасти привязана к JavaScript, чтобы эти программисты могли сделать эти программистытренироваться в классическом ООП более комфортно.Это не , в любом случае, необходимо, но это означает отказ от классических понятий, таких как видимость членов и (тавтологически) конструкторы.
В ответ вы получаете гибкость и простоту.Вы можете создавать «классы» на лету - каждый объект сам является шаблоном для других объектов.Установка значений для дочерних объектов не повлияет на прототип этих объектов (то есть, если бы я использовал var child = Object.create(myHuman)
, а затем установил child.walk = 'not yet'
, animal.walk
не изменилось бы - действительно, протестируйте его).
Простотанаследования честно ошеломляет.Я много читал о наследовании в JavaScript и написал много строк кода, пытаясь понять это.Но это действительно сводится к объектам, наследуемым от других объектов .Это так просто, и все ключевое слово new
запутывает это.
Эту гибкость трудно использовать в полной мере, и я уверен, что мне еще предстоит это сделать, но этотам и интересно ориентироваться.Я думаю, что большая часть причины того, что он не использовался для большого проекта, заключается в том, что он просто не понимается так, как мог бы, и, ИМХО, мы заперты в классических шаблонах наследования, которые мы все изучили, когда мыпреподавали C ++, Java и т. д.
Edit
Я думаю, что я выступил с хорошими аргументами против конструкторов.Но мой аргумент против фабрик нечеткий.
После дальнейшего созерцания, во время которого я несколько раз шлепнулся к обеим сторонам забора, я пришел к выводу, что фабрики также не нужны. Если бы animal
(выше) была дана другая функция initialize
, было бы тривиально создать и инициализировать новый объект, который наследуется от animal
.
var myDog = Object.create(animal);
myDog.initialize(4, 'Meow');
Новый объект, инициализирован и готов к использованию.
@ Raynos - Вы совершенно обалденный снайпер. Я должен готовиться к 5 дням, ничего не делая продуктивно.