Прототип JavaScript

Оригинальное название: JavaScript prototype

Коротко

Объект, к которому JavaScript обращается за свойством или методом, если их нет у самого объекта. Так в языке устроено наследование.

Что такое «Прототип JavaScript»

В большинстве популярных языков наследование строится на классах: класс-потомок расширяет класс-родитель. JavaScript устроен иначе. У каждого объекта есть скрытая ссылка на другой объект — прототип. Когда программа читает свойство, движок сначала ищет его у самого объекта, затем у прототипа, затем у прототипа прототипа, и так до конца цепочки. Последнее звено обычно Object.prototype, а его прототип — null. Если свойство не нашлось нигде, результат — undefined.

Благодаря этому у любого массива есть методы map и filter: они хранятся не в каждом массиве, а один раз в Array.prototype.

Как это выглядит в коде

const product = {
  label() { return `${this.name} — ${this.price}`; }
};

const sofa = Object.create( product ); // product становится прототипом
sofa.name = 'Диван';
sofa.price = 45000;

sofa.label();                             // метод найден в прототипе
Object.getPrototypeOf( sofa ) === product; // true
sofa.hasOwnProperty( 'label' );           // false — своего свойства нет

Прототипы и классы

Синтаксис class появился в ES2015, но внутри работает всё тот же механизм. Методы, объявленные в классе, попадают в объект Имя.prototype, а extends связывает прототипы в цепочку. Поэтому знание прототипов объясняет поведение, которое иначе кажется странным: например, почему метод, изменённый в прототипе, сразу меняется у всех созданных ранее объектов. Классическое наследование в Java или PHP копирует структуру класса, а прототипное — делегирует поиск по живой ссылке.

Чего не делать

  • Не расширять встроенные прототипы вроде Array.prototype своими методами. Старые библиотеки так делали, и это не раз мешало развитию языка: новый стандартный метод конфликтовал с самодельным на тысячах сайтов.
  • Не сливать в объект непроверенный JSON от пользователя рекурсивной функцией. Ключ __proto__ в таких данных может изменить прототип всех объектов приложения — эту уязвимость называют загрязнением прототипа (prototype pollution).
  • Не путать собственные свойства объекта с унаследованными: цикл for...in перебирает и те и другие, а Object.keys() — только собственные.

Обновлено:

Все термины раздела «Backend»

Что будем искать? Например,Продвижение