JS Tower
JavaScript & TypeScriptМодуль 6: ООП и паттерны

Прототипы

Прототипное наследование в JavaScript

Цель урока

В этом уроке ты научишься:

  • Понимать прототипное наследование
  • Работать с цепочкой прототипов
  • Создавать объекты с прототипами

Что такое прототип

Каждый объект имеет скрытую ссылку на другой объект — прототип. При обращении к свойству, которого нет в объекте, JavaScript ищет его в прототипе.

let animal = {
  eats: true,
  walk() {
    console.log("Животное идёт");
  }
};

let rabbit = {
  jumps: true
};

rabbit.__proto__ = animal;

console.log(rabbit.eats);  // true (из прототипа)
console.log(rabbit.jumps); // true (собственное)
rabbit.walk();             // "Животное идёт"

Не используй __proto__

__proto__ устарел. Используй Object.getPrototypeOf и Object.setPrototypeOf.


Object.create

let animal = {
  eats: true,
  walk() {
    console.log("Животное идёт");
  }
};

let rabbit = Object.create(animal);
rabbit.jumps = true;

console.log(rabbit.eats);  // true
console.log(rabbit.jumps); // true

Цепочка прототипов

let animal = {
  eats: true
};

let rabbit = Object.create(animal);
rabbit.jumps = true;

let whiteRabbit = Object.create(rabbit);
whiteRabbit.color = "white";

console.log(whiteRabbit.color); // "white" (собственное)
console.log(whiteRabbit.jumps); // true (от rabbit)
console.log(whiteRabbit.eats);  // true (от animal)

Свойство prototype

Функции-конструкторы имеют свойство prototype:

function Animal(name) {
  this.name = name;
}

Animal.prototype.walk = function() {
  console.log(this.name + " идёт");
};

let rabbit = new Animal("Кролик");
rabbit.walk(); // "Кролик идёт"

// rabbit.__proto__ === Animal.prototype

Проверка прототипов

let animal = { eats: true };
let rabbit = Object.create(animal);

// Проверка прототипа
console.log(Object.getPrototypeOf(rabbit) === animal); // true

// Проверка наследования
console.log(animal.isPrototypeOf(rabbit)); // true

// Собственные свойства
console.log(rabbit.hasOwnProperty("eats")); // false
rabbit.jumps = true;
console.log(rabbit.hasOwnProperty("jumps")); // true

Перебор свойств

let animal = { eats: true };
let rabbit = Object.create(animal);
rabbit.jumps = true;

// for...in перебирает и унаследованные
for (let key in rabbit) {
  console.log(key); // jumps, eats
}

// Только собственные
for (let key in rabbit) {
  if (rabbit.hasOwnProperty(key)) {
    console.log(key); // jumps
  }
}

// Object.keys — только собственные
console.log(Object.keys(rabbit)); // ["jumps"]

Встроенные прототипы

let arr = [1, 2, 3];

// arr → Array.prototype → Object.prototype → null

console.log(arr.__proto__ === Array.prototype);  // true
console.log(arr.__proto__.__proto__ === Object.prototype); // true

// Методы массивов находятся в Array.prototype
console.log(Array.prototype.map);    // function
console.log(Array.prototype.filter); // function

Практика

Задание 1: Создание прототипа

Задача: Создай объект с прототипом.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
4
Едет

Задание 2: Проверка свойств

Задача: Определи, какие свойства собственные.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
["b"]

Проверь себя

  1. Что такое прототип?
  2. Как создать объект с прототипом?
  3. Чем hasOwnProperty отличается от in?