Для чего нужны прототипы в javascript

Встроенные прототипы

Свойство «prototype» широко используется внутри самого языка JavaScript. Все встроенные функции-конструкторы используют его.

Сначала мы рассмотрим детали, а затем используем «prototype» для добавления встроенным объектам новой функциональности.

Object.prototype

Давайте выведем пустой объект:

Вот что происходит:

Когда вызывается new Object() (или создаётся объект с помощью литерала <. >), свойство [[Prototype]] этого объекта устанавливается на Object.prototype по правилам, которые мы обсуждали в предыдущей главе:

Мы можем проверить это так:

Обратите внимание, что по цепочке прототипов выше Object.prototype больше нет свойства [[Prototype]] :

Другие встроенные прототипы

Вот более полная картина (для трёх встроенных объектов):

Давайте проверим прототипы:

В браузерных инструментах, таких как консоль разработчика, можно посмотреть цепочку наследования (возможно, потребуется использовать console.dir для встроенных объектов):

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Примитивы

Самое сложное происходит со строками, числами и булевыми значениями.

Специальные значения null и undefined стоят особняком. У них нет объектов-обёрток, так что методы и свойства им недоступны. Также у них нет соответствующих прототипов.

Изменение встроенных прототипов

В течение процесса разработки у нас могут возникнуть идеи о новых встроенных методах, которые нам хотелось бы иметь, и искушение добавить их во встроенные прототипы. Это плохая идея.

Так что, в общем, изменение встроенных прототипов считается плохой идеей.

В современном программировании есть только один случай, в котором одобряется изменение встроенных прототипов. Это создание полифилов.

Полифил – это термин, который означает эмуляцию метода, который существует в спецификации JavaScript, но ещё не поддерживается текущим движком JavaScript.

Тогда мы можем реализовать его сами и добавить во встроенный прототип.

Заимствование у прототипов

В главе Декораторы и переадресация вызова, call/apply мы говорили о заимствовании методов.

Это когда мы берём метод из одного объекта и копируем его в другой.

Некоторые методы встроенных прототипов часто одалживают.

Например, если мы создаём объект, похожий на массив (псевдомассив), мы можем скопировать некоторые методы из Array в этот объект.

Но это будет невозможно, если obj уже наследует от другого объекта. Помните, мы можем наследовать только от одного объекта одновременно.

Заимствование методов – гибкий способ, позволяющий смешивать функциональность разных объектов по необходимости.

Итого

Задачи

Добавить функциям метод «f.defer(ms)»

Источник

Поделиться

doctor Brain

мир глазами веб-разработчика

Прототипы в JavaScript

Как прототипы в JavaScript влияют на время выполнения кода?

время чтения 3 мин.

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Во времена своего обучения в университете, я заметил, что многие однокурсники, занимающиеся разработкой веб-приложений, не могут понять: зачем и как использовать прототипы в JavaScript.

Для того, чтобы объявить класс необходимо всего лишь создать функцию (хорошей практикой будет использование верблюжьей нотации). В нашем примере класс называется Person:

Прототипы: мы должны переподчинить методы и свойства, которые не должны изменяться при создании объекта, прототипу класса Person:

В JavaScript каждый объект имеет свою цепочку прототипов. Кроме того, у прототипов могут быть свои прототипы. Такой подход позволяет управлять наследованием и переназначать необходимые свойства и методы прототипам более низкого уровня.

Наконец, давайте оценим эффективность использования различных экземпляров класса.

Создадим два различных объекта:

Получены следующие результаты:

Можно сделать вывод, что переподчинение свойств и методов экземпляра класса прототипу позволяет увеличить скорость работы приложения.

Будьте внимательны. Большие цепочки прототипов уменьшают производительность приложения из-за расходования ресурсов на процесс поиска.

Еще больше информации о наследовании и цепочках прототипов можно узнать здесь

Источник

Прототип объекта

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/prototype-inheritance.

Объекты в JavaScript можно организовать в цепочки так, чтобы свойство, не найденное в одном объекте, автоматически искалось бы в другом.

Прототип proto

Свойство __proto__ доступно во всех браузерах, кроме IE10-, а в более старых IE оно, конечно же, тоже есть, но напрямую к нему не обратиться, требуются чуть более сложные способы, которые мы рассмотрим позднее.

Пример кода (кроме IE10-):

Иллюстрация происходящего при чтении rabbit.eats (поиск идёт снизу вверх):

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Обратим внимание – прототип используется исключительно при чтении. Запись значения, например, rabbit.eats = value или удаление delete rabbit.eats – работает напрямую с объектом.

Другими словами, прототип – это «резервное хранилище свойств и методов» объекта, автоматически используемое при поиске.

Метод hasOwnProperty

Обычный цикл for..in не делает различия между свойствами объекта и его прототипа.

Он перебирает всё, например:

Иногда хочется посмотреть, что находится именно в самом объекте, а не в прототипе.

Для того, чтобы перебрать свойства самого объекта, достаточно профильтровать key через hasOwnProperty :

Object.create(null)

Зачастую объекты используют для хранения произвольных значений по ключу, как коллекцию:

Это может быть неприятным сюрпризом и приводить к ошибкам, если названия свойств приходят от посетителя и могут быть произвольными.

Чтобы этого избежать, мы можем исключать свойства, не принадлежащие самому объекту:

Однако, есть путь и проще:

Объект, создаваемый при помощи Object.create(null) не имеет прототипа, а значит в нём нет лишних свойств. Для коллекции – как раз то, что надо.

Методы для работы с proto

Чтение: Object.getPrototypeOf(obj) Возвращает obj.__proto__ (кроме IE8-) Запись: Object.setPrototypeOf(obj, proto) Устанавливает obj.__proto__ = proto (кроме IE10-).

Кроме того, есть ещё один вспомогательный метод:

Итого

В современных браузерах есть методы для работы с прототипом:

Также мы рассмотрим, как свойство __proto__ используется внутри самого языка JavaScript и как организовать классы с его помощью.

Источник

Прототипы в JS и малоизвестные факты

Лирическое вступление

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

Оказалось, что есть много неочевидных вещей из старых времён ES5 и даже ES6, о которых я не слышал. А еще оказалось, что вывод консоли браузера может не соответствовать действительности.

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

Объект в JS имеет собственные и унаследованные свойства, например, в этом коде:

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Как выглядит прототип

Да кто такой этот ваш constructor

constructor – это ссылка на функцию, с помощью которой был создан объект:

Не совсем понятна идея зачем он был нужен, возможно, как способ клонирования объекта:

Но я не нашел подходящий пример его использования, если у Вас есть примеры проектов, где это использовалось, то напишите об этом. В остальном же использовать constructor лучше не стоит, так как это writable свойство, которое можно случайно перезаписать, работая с прототипом, и сломать часть логики.

Где живёт прототип

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

О чем вам недоговаривает дебаггер, или он вам не прототип

Свойство __proto__ является геттером и сеттером для внутреннего слота [[Prototype]] и находится в Object.prototype :

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Из-за этого я избегал записи __proto__ для обозначения прототипа. __proto__ находится не в самом объекте, что приводит к неожиданным результатам. Для демонстрации попробуем через __proto__ удалить прототип объекта и затем восстановить его:

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

В консоли Chrome foo будет выглядеть следующим образом:

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

А теперь уберем связь между baz и Object.prototype :

И теперь в консоли Chrome видим следующий результат:

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Как работать с прототипом объекта

Рассмотрим основные способы работы с прототипом: изменение прототипа и создание нового объекта с указанным прототипом.

А теперь менее категоричный вопрос создания нового объекта с прототипом. Для этого есть следующие способы.
Стандартный способ:

И в случае если отсутствует поддержка всего вышеперечисленного:

Функции и конструкторы

А теперь поговорим про функции и как они работают в качестве конструкторов.

Функция Person тут является конструктором и создает два поля в новом объекте, а цепочка прототипов выглядит так:

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

И теперь вызов user.fullName() вернет строку «John Doe».

Что такое new

На самом деле оператор new не таит в себе никакой магии. При вызове new выполняет несколько действий:

Все эти действия можно сделать силами самого языка, поэтому можно написать свой собственный оператор new в виде функции:

Но начиная с ES6 волшебство пришло и к new в виде свойства new.target, которое позволяет определить, была ли вызвана функция как конструктор с new, или как обычная функция:

new.target будет undefined для обычного вызова функции, и ссылкой на саму функцию в случае вызова через new ;

Наследование

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Фиолетовым цветом обозначены поля объекта (они все находятся в самом объекте, т.к. this у всей цепочки прототипов один), а методы желтым (находятся в прототипах соответствующих функций)
Вариант 1 предпочтительнее, т.к. Object.setPrototypeOf может привести к проблемам с производительностью.

Сколько вам сахара к классу

Для того чтобы облегчить классическую схему наследование и предоставить более привычный синтаксис, были представлены классы, просто сравним код с примерами Person и Student:

Уменьшился не только бойлерплейт, но и поддерживаемость:

При этом цепочка прототипов получается идентичной примеру с явным указанием prototype у функций конструкторов.

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

P. P. S.

К сожалению главный кликбейт статьи перестал быть актуальным. В данный момент Chrome (версия 93, на момент обновления статьи) перестал использовать __proto__ для обозначения прототипа, и теперь отображает его как слот [[Prototype]] :

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Справедливости ради хочу отметить что в Firefox (92) также не используется обозначение __proto__ :

Источник

Прототипы объектов

Базовая компьютерная грамотность, базовое понимание HTML и CSS, знакомство с основами JavaScript (см. Первые шаги и Строительные блоки) и основы OOJS (см. Введение в объекты).

Понять прототипы объектов JavaScript, как работают прототипные цепочки и как добавить новые методы в prototype свойство.

Язык основанный на прототипах?

JavaScript часто описывают как язык прототипного наследования — каждый объект, имеет объект-прототип, который выступает как шаблон, от которого объект наследует методы и свойства. Объект-прототип так же может иметь свой прототип и наследовать его свойства и методы и так далее. Это часто называется цепочкой прототипов и объясняет почему одним объектам доступны свойства и методы которые определены в других объектах.

Точнее, свойства и методы определяются в свойстве prototype функции-конструктора объектов, а не в самих объектах.

Давайте посмотрим на пример, чтобы стало понятнее.

Понимание прототипа объектов

В этом примере мы определили конструктору функцию, например:

Затем мы создаём экземпляр объекта следующим образом:

Если вы наберёте « person1. » в вашей консоли JavaScript, вы должны увидеть, что браузер пытается автоматически заполнить это с именами участников, доступных на этом объекте:

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Для чего нужны прототипы в javascript. Смотреть фото Для чего нужны прототипы в javascript. Смотреть картинку Для чего нужны прототипы в javascript. Картинка про Для чего нужны прототипы в javascript. Фото Для чего нужны прототипы в javascript

Свойство prototype: Где определены унаследованные экземпляры

Снова create()

Ранее мы показали, как метод Object.create() может использоваться для создания нового экземпляра объекта.

Свойство constructor

Это хорошо работает. Вам не нужно будет использовать его часто, но это может быть действительно полезно, если вы хотите создать новый экземпляр и не имеете ссылки на исходный конструктор, который легко доступен по какой-либо причине.

Свойство constructor имеет другие применения. Например, если у вас есть экземпляр объекта и вы хотите вернуть имя конструктора этого экземпляра, вы можете использовать следующее:

Например, попробуйте это:

Изменение прототипов

Давайте рассмотрим пример изменения свойства prototype функции-конструктора — методы, добавленные в прототип, затем доступны для всех экземпляров объектов, созданных из конструктора.

Должно появиться всплывающее окно, с именем пользователя, определённым в конструкторе. Это действительно полезно, но ещё более полезно то, что вся цепочка наследования обновляется динамически, автоматически делая этот новый метод доступным для всех экземпляров объектов, полученных из конструктора.

Подумайте об этом на мгновение. В нашем коде мы определяем конструктор, затем мы создаём экземпляр объекта из конструктора, затем добавляем новый метод к прототипу конструктора:

Примечание: Если у вас возникли проблемы с получением этого примера для работы, посмотрите на наш пример oojs-class-prototype.html (см. также это running live).

Это не очень гибко, так как человека нельзя назвать так. Было бы намного лучше сделать это, создав fullName из name.first и name.last :

Этот образец можно увидеть в действии в примере приложения плана школы Петра Залевы.

Резюме

В этой статье рассмотрены прототипы объектов JavaScript (в том числе и то, как прототип цепочки объектов позволяет объектам наследовать функции друг от друга), свойство прототипа и как его можно использовать для добавления методов к конструкторам и другие связанные с этой статьёй темы.

В следующей статье мы рассмотрим то, как вы можете реализовать наследование функциональности между двумя собственными настраиваемыми объектами.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *