Прототипное наследование в Javascript

Несмотря на то, что может быть сказано в моем резюме, я многого не знаю о Javascript. Я часто вижу слово «монада». Не совсем уверен, как эти «сборщики мусора» говорят о своих работах (может быть, если бы я принес ему гаторрейд?). JS имеет типизированные массивы?

Из всех загадок этого языка программирования самой загадочной из них были прототипы. Я продолжал видеть прототип повсюду и понятия не имел, что это значит. Итак, в выпуске блога на этой неделе я собираюсь поговорить о прототипах и наследовании в Javascript.

Что такое прототип?

В Javascript прототип - это объект, из которого черпают функции другие объекты и структуры данных. Функции, массивы, объекты, строки и даже числа имеют прототипы, хотя по какой-то причине без моего ведома вы не можете вызывать __proto__ на 2, например. Также __proto__ является устаревшим выражением для просмотра объекта-прототипа объекта.

Javascript широко считается языком, основанным на прототипах. Для наследования методов и свойств у объектов есть объект-прототип, который действует как шаблон.

Я слышал хороший пример, в котором прототипное наследование приравнялось к тому, чтобы одолжить карандаш в школе, что сделали многие из нас в американской системе государственных школ (и, возможно, в других местах). Предположим, вы посещаете класс, например всемирную историю, и учитель раздает всем лист регистрации, чтобы каждый мог выбрать страну для исследования. Лист регистрации попадает к вам, но у вас нет ручки или карандаша. Итак, вы хлопаете друга, который сидит рядом с вами, по плечу и говорите: «Эй, могу я одолжить твой карандаш, я забыл свой сегодня, но клянусь, я принесу один завтра и навсегда, ха-ха». И твой друг вздрагивает и говорит: «О боже, как бы я хотел, чтобы ты не сказал этого, потому что на самом деле у меня тоже нет карандаша, я хотел спросить тебя, когда мне достанется лист. Хотя подожди… »И ваш друг похлопывает другого друга по плечу и повторяет вопрос, на который тот друг отвечает:« О да, просто отдай его мне, когда закончишь », и застегнул молнию. Увеличьте масштаб, ваш друг берет карандаш, передает его вам, и теперь вы все зарегистрированы в Италии.

Надеюсь, это говорит само за себя, но в приведенном выше примере вы представляете объект в Javascript. Ваш друг и другой друг являются объектами того, что мы называем прототипной цепочкой, а желанный карандаш - функцией, которая передается вам по цепочке.

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

Это если они ваш прототип. Странная аналогия, ну да ладно.

Вот небольшой фрагмент кода для предыдущего примера. У моего друга «Томсона» есть функция pencilAccess, а также свойство grade. В строке 14 я использую функцию setPrototypeOf (которая сама является функцией прототипа Object), чтобы установить старого доброго Томсона в качестве моего прототипа. Так я смогу использовать его карандаш, и он сможет напоминать мне, в каком мы классе.

Это если мы учимся в одном классе.

Зачем мне нужны прототипы?

Пока я смотрел видео, читал статьи и разбирал документацию, меня мучил один вопрос: ну и что? Я знал, что всякий раз, когда мне нужно напоминать о том, как функция splice работает с массивами, я вижу «Array.prototype» вверху страницы, или когда я проверяю или выхожу из системы, я мог видеть что-то вроде .__proto__, но почему мне все равно?

  1. Как я уже сказал, Javascript описывается как язык «на основе прототипов». Было бы неплохо узнать, на чем основан Javascript, чтобы иметь полное представление об инструментах. Также, если что-то не так, может быть, это как-то связано с прототипами? Стоит попробовать.
  2. Изучение прототипного наследования ведет к изучению наследования в программировании в целом, и распространенной темой является использование наследования классов по сравнению с темой этой статьи. Поэтому давайте обсудим, что я узнал об этом.

Как вы, возможно, знаете, объектно-ориентированные языки программирования полагаются на классы. Класс часто сравнивают с планом. Используя его, вы можете создавать новые экземпляры объектов со свойствами и методами, которые определены в схеме для этого объекта, его класса. Давайте окунемся в другой (избитый) пример!

Допустим, вы работаете на клиента, который хочет моделировать животных в приложении. Вы начинаете с создания класса Cat и определения пары вещей, которые кошка может делать, например, мяукать, может быть, она порода и тому подобное. Затем вы переходите к созданию класса «Собака», и собаки «ядда ядда» лают, кошки мяукают, но вы понимаете, что есть несколько вещей, которые делают и кошки, и собаки, которые клиент хочет включить, например, есть, или, может быть, принять ванну или что-то в этом роде. Итак, вы создаете класс Animal с этими центральными функциями и говорите, что Cats и Dogs наследуются от класса Animal. Здорово.

Но теперь клиент возвращается и говорит: «Привет, пока такая отличная работа. Ситуация меняется, и мы хотим, чтобы пользователи видели животных-роботов ». Теперь это создает некоторые проблемы для структуры ваших классов, потому что RobotDog не нужно есть. Это робот, и, может быть, ему нужно заправиться или добавить смазку, я не знаю. Так что, возможно, вы также создадите класс RobotAnimal, но тогда вы поймете, что и Dog, и RobotDog потребуется доступ к функции лая. Ура, достаточно сказать, что с растущим приложением решения, которые принимаются для наследования на основе классов, не самые гибкие и могут помешать разработчику писать избыточный, неэффективный код.

Кроме того, когда класс наследуется от другого класса, все методы родительского класса передаются дочернему. Вот почему во многих статьях, которые я читаю, есть упоминания о так называемой «проблеме бананов». Проблема в том, что при классическом наследовании, когда вы хотите банан, вы получаете этот банан, но часто также получаете гориллу, которая держит банан, а также окружающие джунгли.

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

Также стоит отметить, что, хотя это более эффективно и перспективно, чем классическое наследование, идеальным решением является использование композиции объектов, которая выходит за рамки этой статьи, но прекрасно объясняется в этом прекрасном видео:

Движение вперед

Это основа прототипов и того, как наследование работает в Javascript. Нам предстоит еще многое узнать: нюансы и вариации в том, как создаются объекты, ключевое слово this, относительно недавнее ключевое слово class в Javascript, которое, честно говоря, кажется немного глупым, и функции конструктора для объектов. На самом деле просто хотел не запутаться, когда я вижу слово «прототип» во всем документе Mozilla. Я многим обязан нескольким ресурсам, которые помогли мне лучше понять эту тему, поэтому я опубликую их ниже. Надеюсь, это помогло!

Другие источники

  1. Отличная серия по созданию объектов на Javascript
  2. Документ Mozilla о наследовании и цепочке прототипов
  3. Документ Mozilla о прототипах объектов, ха-ха