Прототипы объектов в JS
В этом уроке узнаете, что такое прототипы объектов и как с ними работать.
Прежде чем изучать прототипы, убедитесь, что вы хорошо ознакомлены со следующими темами.
- Объекты в JS
- Конструктор объектов в JS
Если вы не знакомы с этими темами— у нас есть соответствующие статьи.
Что надо знать
В JavaScript объект можно создать с помощью функции-конструктора. Например,
// функция-конструктор
function Person () {
this.name = 'Андрей',
this.age = 23
}
// создание объектов с помощью конструктора
const person1 = new Person();
const person2 = new Person();
Прототипы объектов
У каждой функции и объекта по умолчанию есть свойство с именем prototype
. Например,
function Person () {
this.name = 'Андрей',
this.age = 23
}
const person = new Person();
// проверяем значение свойства prototype
console.log(Person.prototype); // Вывод: { ... }
В этом примере мы пытаемся получить доступ к свойству prototype
функции-конструктора Person
.
Поскольку свойство prototype
в данный момент не имеет значения, оно показывает пустой объект { ... }
.
Наследование с помощью prototype
В JavaScript прототипы можно использовать для добавления свойств и методов в функцию-конструктор. Объекты наследуют свойства и методы от прототипа. Например,
// функция-конструктор
function Person () {
this.name = 'Андрей',
this.age = 23
}
// создаем объект
const person1 = new Person();
const person2 = new Person();
// добавляем свойство в конструктор
Person.prototype.gender = 'М';
// значение prototype конструктора Person
console.log(Person.prototype);
// наследование свойства от прототипа
console.log(person1.gender);
console.log(person2.gender);
Вывод:
{ gender: "М" } М М
В этом примере мы добавили новое свойство gender
в функцию-конструктор Person
следующим образом:
Person.prototype.gender = 'М';
Как видно из вывода, объекты person1
и person2
наследуют свойство gender
из свойства prototype
функции конструктора Person
.
Следовательно, из обоих объектов person1
и person2
можно получить доступ к свойству gender
.
Примечание. Синтаксис для добавления свойства в функцию конструктора объекта следующий:
objectConstructorName.prototype.ключ = 'значение';
Прототипы используют для предоставления дополнительных свойств всем объектам, созданным из функции конструктора.
Добавление методов в функцию-конструктор с помощью prototype
В функцию-конструктор с помощью prototype можно добавлять не только новые свойства, но и методы. Например,
// функция-конструктор
function Person () {
this.name = 'John',
this.age = 23
}
// создаем объекты
const person1 = new Person();
const person2 = new Person();
// добавляем новый метод в функцию-конструктор
Person.prototype.greet = function() {
console.log('Привет, я ' + this.name);
}
person1.greet(); // Вывод: Привет, я Андрей
person2.greet(); // Вывод: Привет, я Андрей
В этом примере мы к функции конструктора Person с помощью prototype добавили новый метод greet
.
Изменение прототипа
Если изменить значение прототипа, то оно изменится у всех новых объектов. У всех ранее созданных объектов сохранится прежнее значение. Например,
// функция-конструктор
function Person() {
this.name = 'Андрей'
}
// добавление свойства
Person.prototype.age = 20;
// создание объекта
const person1 = new Person();
console.log(person1.age); // Вывод: 20
// изменение значения прототипа
Person.prototype = { age: 50 }
// создание нового объекта
const person3 = new Person();
console.log(person3.age); // Вывод: 50
console.log(person1.age); // Вывод: 20
Совет. Не стоит изменять прототипы стандартных встроенных объектов JavaScript, таких как строки, массивы и т.п.
Цепочка прототипов
Если объект попытается получить доступ к одному и тому же свойству, которое находится в функции конструктора и в объекте-прототипе, объект возьмет свойство из функции конструктора. Например,
function Person() {
this.name = 'Андрей'
}
// добавляем свойства
Person.prototype.name = 'Дима';
Person.prototype.age = 23
const person1 = new Person();
console.log(person1.name); // Вывод: Андрей
console.log(person1.age); // Вывод: 23
В приведенном выше примере свойство name
объявлено в функции-конструкторе, а также в свойстве prototype
.
person1.name
ищет свойствоname
в функции-конструкторе. Поскольку в функции-конструкторе есть свойствоname
(со значением'Андрей'
), объект берет значение из этого свойства.person1.age
ищет свойствоage
в функции-конструкторе. Поскольку в функции-конструкторе нет свойстваage
, программа просматривает объект-прототип функции-конструктора, и объект наследует свойство от объекта-прототипа (если оно доступно).
Примечание. Получить доступ к свойству prototype функции-конструктора можно и из объекта.
function Person () {
this.name = 'Андрей'
}
// добавляем прототип
Person.prototype.age = 24;
// создаем объект
const person = new Person();
// получаем доступ к prototype из объекта
console.log(person.__proto__); // { age: 24 }
В этом примере объект person
доступается к свойству prototype
с помощью __proto__.
На самом деле, такой подход уже устарел и по возможности лучше избегать его.