Главная->Уроки по js->Прототипы в JS

Прототипы в JS

07 Июн в 00:00

Прототип - это JS объект, от которого другие объекты наследуют его свойства и методы. По умолчанию, у каждого объекта есть свой прототип и если у искомого объекта не хватает каких-либо свойств, то они ищутся в прототипе. В свою очередь, если и у ближайшего прототипа нет этих свойств, то они ищутся ниже в иерархии прототипов. По такому принципу происходит наследование прототипов в JS. На вершине цепочки прототипов, находится последний прототип (стандартный объект JavaScript), выше которого уже ничего нет. Прототип объекта в JS Чтобы увидеть __proto__ в консоли разработчика, создадим объект - машина. let car = { model: 'Mazda' }; console.log(car); В консоли вывелось название типа данных - object, внутри которого мы видим ссылку __proto__. Эта ссылка ведет на прототип объекта car. Внутри ссылки мы можем увидеть всю цепочку прототипов, которая рано или поздно закончится значением null. Прототипы в JS. Пример с консолью, нам наглядно показывает весь механизм наследования прототипов в JS, но практической пользы от этого нет. Все равно все свойства у прототипов, мы будем писать сами. Прототип функции в JS А использовать мы будем свойство, которое есть у каждой функции - prototype. Создадим новый объект user вторым способом, пропишем внутри объекта два свойства и одну функцию, которая будет выводить в консоль строку Privet. const user = new Object ({ nickname: 'sorax', age: 25, write: function(){ console.log('Privet') } }); Убедимся, что в консоли мы имеем доступ к полям объекта, обратившись к ним по названию объекта через точку по ключу. Прототипы в JS. Хорошо, пойдем дальше и если введем в консоль такую запись. user.toString() то на выходе получим не ошибку, а следующую запись: "[object Object]" Откуда взялась функция toString? Выведем в консоль объект user и увидим знакомую нам ссылку __proto__. Если мы раскроем эту ссылку, то среди внушительного списка методов, мы увидим toString. Это значит, метод toString перешел к объекту user по наследству. У всех новых созданных объектов обязательно есть прототип. Обратимся к свойству prototype у глобального класса Object и создадим новое поле - функцию sayHello. Object.prototype.sayHello = function(){ console.log('Hello') } Вызовем в консоли новую функцию у объекта user. Никакой ошибки не возникло, функция отработала и вывела Hello. user.sayHello() Hello Обратите внимание, что у объекта user не было функции sayHello, но эта функция появилась у его родителя. Получается, что объект user унаследовал её от родителя (прототипа Object). Таким образом, мы можем добавлять новые методы и свойства не напрямую в текущий объект, а через его прототип. Что это даёт? Например, можно через общий прототип (класс) быстро вносить изменения в тысячи аккаунтов пользователей. Создадим нового пользователя fantomas. Передадим в метод create объект user, который будет служить прототипом у нового объекта fantomas. const fantomas = Object.create(user); Напечатаем в консоли слово fantomas и нажмем Enter. На верхнем уровне у нас создался пустой объект, что логично. Ведь никаких полей для него, мы не создавали. Но внутри пустого объекта, мы опять увидим __proto__: Object. {} Поэтому, если мы напишем fantomas.write(), то увидим в консоли Privet. Как так получилось? У самого объекта fantomas, нет ничего. Выходит, что fantomas, унаследовал функцию write у прототипа. У объекта fantomas должен быть свой ник, который записался на верхний уровень цепочки наследования. При этом, на более низком уровне старый ник sorax, не перезаписался. fantomas.nickname = 'fantomas' Как работает механизм цепочки наследования? Он проверяет сверху вниз, если на верхнем уровне находит какое-то свойство или функцию, то сразу её вызывает. Если он ничего не находит, тогда обращается к прототипу и ищет в нём. И если, ничего не найдено по всей цепочке прототипов, то выдается ошибка. С помощью прототипов, можно легко расширять свойства или методы объектов.