HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p><em>В этом уроке дается небольшое введение в тему прототипов. Полностью раскрыть её одним уроком невозможно. Не хватит даже целого курса. Прототипы познаются только через практику, перемешанную с теоретической подготовкой. Поэтому не переживайте, если не всё поймёте с первого раза, это нормально.</em></p>
1 <p><em>В этом уроке дается небольшое введение в тему прототипов. Полностью раскрыть её одним уроком невозможно. Не хватит даже целого курса. Прототипы познаются только через практику, перемешанную с теоретической подготовкой. Поэтому не переживайте, если не всё поймёте с первого раза, это нормально.</em></p>
2 <p>Прототипы - это механизм, который оказывает основное влияние на то, как работают объекты в JavaScript. Сами они напрямую в коде используются редко (и обычно только в библиотеках), но их знание важно для понимания поведения кода и отладки. Особенно при работе с классами, которые мы изучим дальше по курсу. В этом уроке мы затронем только самые основы. Глубоко разобраться с прототипами поможет наш курс, указанный в дополнительных материалах.</p>
2 <p>Прототипы - это механизм, который оказывает основное влияние на то, как работают объекты в JavaScript. Сами они напрямую в коде используются редко (и обычно только в библиотеках), но их знание важно для понимания поведения кода и отладки. Особенно при работе с классами, которые мы изучим дальше по курсу. В этом уроке мы затронем только самые основы. Глубоко разобраться с прототипами поможет наш курс, указанный в дополнительных материалах.</p>
3 <p>В JavaScript с каждым объектом связан прототип. Прототип - это обычный объект, хранящийся в специальном служебном поле [[prototype]] (к этому полю невозможно обратиться напрямую). Его можно извлечь так:</p>
3 <p>В JavaScript с каждым объектом связан прототип. Прототип - это обычный объект, хранящийся в специальном служебном поле [[prototype]] (к этому полю невозможно обратиться напрямую). Его можно извлечь так:</p>
4 <h2>Для чего нужны прототипы</h2>
4 <h2>Для чего нужны прототипы</h2>
5 <p>Представим, что мы обращаемся к свойству объекта, и при этом никакого свойства в этом объекте нет. В таком случае мы получим значение undefined. Обычно это так и работает, но есть одна важная особенность.</p>
5 <p>Представим, что мы обращаемся к свойству объекта, и при этом никакого свойства в этом объекте нет. В таком случае мы получим значение undefined. Обычно это так и работает, но есть одна важная особенность.</p>
6 <p>Если свойства в объекте нет, то JavaScript смотрит прототип этого объекта. Если в прототипе есть искомое свойство, то его значение возвращается. В итоге мы можем обратиться к свойству, которого нет в объекте, но есть в прототипе. И тогда мы получим из прототипа какое-то значение.</p>
6 <p>Если свойства в объекте нет, то JavaScript смотрит прототип этого объекта. Если в прототипе есть искомое свойство, то его значение возвращается. В итоге мы можем обратиться к свойству, которого нет в объекте, но есть в прототипе. И тогда мы получим из прототипа какое-то значение.</p>
7 <p>В реальности процесс еще сложнее. Если свойство не найдено в прототипе, то JavaScript смотрит прототип прототипа и так далее. Так он проходит до конца цепочки прототипов, то есть до последнего прототипа - это всегда null. На базе этого механизма реализуется наследование. Эта тема выходит за рамки текущего урока.</p>
7 <p>В реальности процесс еще сложнее. Если свойство не найдено в прототипе, то JavaScript смотрит прототип прототипа и так далее. Так он проходит до конца цепочки прототипов, то есть до последнего прототипа - это всегда null. На базе этого механизма реализуется наследование. Эта тема выходит за рамки текущего урока.</p>
8 <p>Прототипы есть даже у обычных JavaScript-объектов:</p>
8 <p>Прототипы есть даже у обычных JavaScript-объектов:</p>
9 <p>Именно по этой причине даже пустые объекты содержат свойства и методы:</p>
9 <p>Именно по этой причине даже пустые объекты содержат свойства и методы:</p>
10 <p>Доступ к прототипу можно получить не только из объектов, но и из свойства prototype конструктора, который эти объекты создаёт:</p>
10 <p>Доступ к прототипу можно получить не только из объектов, но и из свойства prototype конструктора, который эти объекты создаёт:</p>
11 <p>Теперь мы можем ответить на вопрос, откуда берется прототип. Прототип - это объект, находящийся в свойстве prototype функции-конструктора, а не сам конструктор. Проверить работу прототипов достаточно легко, изменив их:</p>
11 <p>Теперь мы можем ответить на вопрос, откуда берется прототип. Прототип - это объект, находящийся в свойстве prototype функции-конструктора, а не сам конструктор. Проверить работу прототипов достаточно легко, изменив их:</p>
12 <p>При этом никто не мешает заменить значение свойства getName в конкретном объекте. Это никаким образом не отразится на других объектах, так как они извлекают getName из прототипа:</p>
12 <p>При этом никто не мешает заменить значение свойства getName в конкретном объекте. Это никаким образом не отразится на других объектах, так как они извлекают getName из прототипа:</p>
13 <p>Создание свойств через прототип - и есть правильный способ создания своих абстракций в JavaScript. Любая новая абстракция, которая нам нужна в коде, должна выглядеть как конструктор и прототип, наполненный нужными свойствами.</p>
13 <p>Создание свойств через прототип - и есть правильный способ создания своих абстракций в JavaScript. Любая новая абстракция, которая нам нужна в коде, должна выглядеть как конструктор и прототип, наполненный нужными свойствами.</p>
14 <p>Что даёт этот механизм?</p>
14 <p>Что даёт этот механизм?</p>
15 <p>Самое простое - расширение ядра языка и библиотек без прямого доступа к исходному коду. Прототипы - невероятно гибкий механизм, который позволяет менять всё что угодно из любого места программы в рантайме, то есть во время работы. Например, мы можем добавить или заменить любые методы в любых объектах самого языка:</p>
15 <p>Самое простое - расширение ядра языка и библиотек без прямого доступа к исходному коду. Прототипы - невероятно гибкий механизм, который позволяет менять всё что угодно из любого места программы в рантайме, то есть во время работы. Например, мы можем добавить или заменить любые методы в любых объектах самого языка:</p>
16 <p>Как и любой другой мощный механизм, прототипы опасны. Можно наменять такого, что программирование превратится в ад:</p>
16 <p>Как и любой другой мощный механизм, прототипы опасны. Можно наменять такого, что программирование превратится в ад:</p>
17 <p>Но если использовать этот механизм с умом, то можно получить очень много хорошего. Например, прототипы активно используются в<a>тестировании</a>, они помогают подменить вызовы нежелательных методов, которые выполняют HTTP-запросы. Другой популярный вариант -<a>полифилы</a>. Это код, который добавляет в старые версии JavaScript возможности из новых версий, но не все, конечно - только те, что появляются в виде свойств и методов.</p>
17 <p>Но если использовать этот механизм с умом, то можно получить очень много хорошего. Например, прототипы активно используются в<a>тестировании</a>, они помогают подменить вызовы нежелательных методов, которые выполняют HTTP-запросы. Другой популярный вариант -<a>полифилы</a>. Это код, который добавляет в старые версии JavaScript возможности из новых версий, но не все, конечно - только те, что появляются в виде свойств и методов.</p>
18 <p>Теперь вы знаете, почему в документации все имена функций описаны так: Number.prototype.toLocaleString().</p>
18 <p>Теперь вы знаете, почему в документации все имена функций описаны так: Number.prototype.toLocaleString().</p>