Прототипы объектов в 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__. На самом деле, такой подход уже устарел и по возможности лучше избегать его. 

codechick

СodeСhick.io - простой и эффективный способ изучения программирования.

2024 ©