Skip to content

Практическая работа №7

Основные теоретические положения

Section titled “Основные теоретические положения”

1. Собственные и унаследованные свойства

Объект может содержать собственные свойства и получать свойства или методы через прототип.

const user = {
name: "Иван",
};
console.log(user.name);
console.log(user.toString());

Свойство name принадлежит самому объекту, а метод toString() доступен через прототипную цепочку.

Проверить собственное свойство можно так:

console.log(Object.hasOwn(user, "name"));
console.log(Object.hasOwn(user, "toString"));

2. Получение прототипа объекта

Для получения непосредственного прототипа используйте:

Object.getPrototypeOf(object)

Пример:

const user = {
name: "Иван",
};
console.log(Object.getPrototypeOf(user));

3. Создание объекта с заданным прототипом

const userPrototype = {
showInfo() {
console.log(`Пользователь: ${this.name}`);
},
};
const user = Object.create(userPrototype);
user.name = "Анна";
user.showInfo();

Метод showInfo() не является собственным свойством user, но доступен через его прототип.


4. Поиск свойства по цепочке прототипов

При обращении:

object.property

JavaScript:

  1. ищет свойство в самом объекте;
  2. если его нет — в прототипе;
  3. затем в прототипе прототипа;
  4. поиск заканчивается на null.

Схематично:

object
↓
prototype
↓
Object.prototype
↓
null

5. Переопределение унаследованного свойства

const prototype = {
role: "user",
};
const admin = Object.create(prototype);
console.log(admin.role); // user
admin.role = "admin";
console.log(admin.role); // admin

При присваивании создаётся собственное свойство объекта. Прототип при этом не изменяется.


6. Функция-конструктор

До появления синтаксиса class объекты одного типа часто создавались через функции-конструкторы.

function User(name, age) {
this.name = name;
this.age = age;
}
const user1 = new User("Иван", 20);
const user2 = new User("Анна", 19);

При использовании new создаётся новый объект, а его прототип связывается с:

User.prototype

Проверка:

console.log(
Object.getPrototypeOf(user1) === User.prototype
);

7. Общие методы через prototype

Не следует создавать одинаковую функцию отдельно в каждом экземпляре:

function User(name) {
this.name = name;
this.showInfo = function () {
console.log(this.name);
};
}

Предпочтительнее разместить общий метод в прототипе:

function User(name) {
this.name = name;
}
User.prototype.showInfo = function () {
console.log(this.name);
};

Тогда экземпляры используют один общий метод.


8. Прототипное наследование функций-конструкторов

Базовый конструктор:

function User(name) {
this.name = name;
}
User.prototype.showInfo = function () {
console.log(this.name);
};

Производный конструктор:

function Admin(name, permissions) {
User.call(this, name);
this.permissions = permissions;
}

Настройка цепочки прототипов:

Admin.prototype = Object.create(User.prototype);
Admin.prototype.constructor = Admin;

Новый метод:

Admin.prototype.showPermissions = function () {
console.log(this.permissions);
};

9. Переопределение метода

Admin.prototype.showInfo = function () {
console.log(`Администратор: ${this.name}`);
};

Теперь экземпляр Admin использует собственную реализацию метода, найденную раньше по цепочке прототипов.


10. Связь с дальнейшим class

Синтаксис class, который будет использоваться в следующей практической работе, не отменяет прототипы.

Даже объект, созданный через класс, продолжает использовать цепочку прототипов.

Поэтому задача этой практической работы — понять механизм, на котором построена объектная модель JavaScript.

Задания для выполнения

Section titled “Задания для выполнения”

Часть 1. Исследование прототипной модели

Выполните задания 1–4 полностью.


Задание 1.1. Собственные и унаследованные свойства

Создайте:

const user = {
name: "Иван",
age: 20,
};

Выведите результаты:

Object.hasOwn(user, "name")
Object.hasOwn(user, "toString")
"name" in user
"toString" in user

Объясните различие между Object.hasOwn() и оператором in.


Задание 1.2. Создание объекта через Object.create()

Создайте прототип:

const accountPrototype = {
showInfo() {
alert(
`Логин: ${this.login}\n` +
`Активен: ${this.active}`
);
},
};

Создайте два объекта через Object.create(accountPrototype).

Добавьте им собственные свойства:

login
active

Вызовите showInfo() для каждого.

Проверьте:

Object.getPrototypeOf(account1) === accountPrototype

Задание 1.3. Переопределение метода

Добавьте в прототип:

getAccessLevel()

который возвращает строку:

Обычный доступ

Для одного объекта создайте собственный метод getAccessLevel(), возвращающий:

Расширенный доступ

Проверьте оба объекта и объясните, почему результат различается.


Задание 1.4. Функция-конструктор

Создайте:

function Product(id, name, price) {
this.id = id;
this.name = name;
this.price = price;
}

Добавьте через Product.prototype методы:

showInfo()
changePrice(newPrice)

Создайте минимум три товара и сохраните их в массив.

Проверьте:

Object.getPrototypeOf(products[0]) === Product.prototype

Часть 2. Комплексное индивидуальное задание

Section titled “Часть 2. Комплексное индивидуальное задание”

Вариант 1. Пользователи и администраторы

Создайте функции-конструкторы:

User
Admin

User:

id
name
active

Методы:

showInfo()
activate()
deactivate()

Admin наследуется от User и дополнительно содержит:

permissions

Добавьте метод:

showPermissions()

Переопределите showInfo().

Программа должна позволять показать пользователей, найти пользователя по id, изменить активность и вывести администраторов.


Вариант 2. Устройства и сетевые устройства

Создайте:

Device
NetworkDevice

Device:

id
name
online

Методы:

showInfo()
turnOn()
turnOff()

NetworkDevice дополнительно:

ip

Метод:

changeIp()

Переопределите showInfo() так, чтобы отображался IP-адрес.


Вариант 3. Транспорт и автомобили

Создайте:

Vehicle
Car

Vehicle:

id
brand
speed

Методы:

showInfo()
accelerate(value)
stop()

Car дополнительно:

fuel

Добавьте:

refuel(amount)

Переопределите showInfo().

Не допускайте отрицательную скорость и количество топлива.


Вариант 4. Персонажи и воины

Создайте:

Character
Warrior

Character:

name
health
level

Методы:

showInfo()
takeDamage(value)
heal(value)

Warrior дополнительно:

armor

Добавьте метод:

takeDamage()

с переопределённой логикой: броня уменьшает получаемый урон.


Вариант 5. Товары и цифровые товары

Создайте:

Product
DigitalProduct

Product:

id
name
price

Методы:

showInfo()
changePrice()

DigitalProduct дополнительно:

fileSize
downloadLink

Переопределите showInfo() и добавьте:

getDownloadInfo()

Вариант 6. Заявки и инциденты

Создайте:

Ticket
Incident

Ticket:

id
title
status

Методы:

showInfo()
changeStatus()

Incident дополнительно:

priority

Добавьте:

isCritical()

Переопределите showInfo().


Вариант 7. Банковские счета и премиальные счета

Создайте:

Account
PremiumAccount

Account:

id
owner
balance

Методы:

showInfo()
deposit()
withdraw()

PremiumAccount дополнительно:

cashbackPercent

Добавьте:

calculateCashback(amount)

Переопределите showInfo().

Не допускайте списание суммы больше баланса.


Вариант 8. Сотрудники и руководители

Создайте:

Employee
Manager

Employee:

id
name
salary

Методы:

showInfo()
changeSalary()

Manager дополнительно:

department
bonus

Добавьте:

calculateTotalIncome()

Переопределите showInfo().


Вариант 9. Медиафайлы и видео

Создайте:

MediaFile
VideoFile

MediaFile:

id
name
size

Методы:

showInfo()
rename()

VideoFile дополнительно:

duration
resolution

Добавьте:

getVideoInfo()

Переопределите showInfo().


Вариант 10. Бронирования и VIP-бронирования

Создайте:

Booking
VipBooking

Booking:

id
guest
price

Методы:

showInfo()
changePrice()

VipBooking дополнительно:

discount
service

Добавьте:

calculateFinalPrice()

Переопределите showInfo().

Требования к результату

Section titled “Требования к результату”

Программа должна:

  • использовать прототипную модель без class;
  • содержать минимум две связанные функции-конструктора;
  • хранить общие методы в prototype;
  • иметь корректно настроенную цепочку прототипов;
  • использовать массив экземпляров;
  • содержать поиск и изменение данных;
  • содержать хотя бы одно переопределение метода;
  • использовать интерактивный ввод;
  • обрабатывать ошибочный ввод;
  • демонстрировать результаты Object.getPrototypeOf().

Что предоставить преподавателю

Section titled “Что предоставить преподавателю”
  • исходный код JavaScript;
  • выполненную общую часть;
  • комплексный вариант;
  • демонстрацию работы программы;
  • вывод проверки цепочки прототипов;
  • объяснение, какие свойства являются собственными, а какие методы — унаследованными.
  1. Что такое прототип объекта?
  2. Что представляет собой цепочка прототипов?
  3. Как получить прототип объекта?
  4. Для чего используется Object.create()?
  5. Чем собственное свойство отличается от унаследованного?
  6. Для чего используется Object.hasOwn()?
  7. Чем Object.hasOwn() отличается от оператора in?
  8. Где JavaScript ищет свойство, отсутствующее в объекте?
  9. Что происходит при создании собственного свойства с тем же именем, что и у прототипа?
  10. Что такое функция-конструктор?
  11. Для чего используется оператор new?
  12. Что хранится в свойстве prototype функции-конструктора?
  13. Почему общие методы лучше хранить в prototype?
  14. Как проверить связь экземпляра с Constructor.prototype?
  15. Для чего используется call() при наследовании?
  16. Зачем после Object.create() восстанавливать свойство constructor?
  17. Что называется переопределением метода?
  18. Почему class в JavaScript не отменяет прототипы?
  19. Почему __proto__ не рекомендуется использовать в прикладном коде?
  20. Как связаны экземпляр, Constructor.prototype и Object.prototype?

Рекомендуемая литература

Section titled “Рекомендуемая литература”
  1. MDN Web Docs — Object prototypes
  2. MDN Web Docs — Inheritance and the prototype chain
  3. MDN Web Docs — Object.create()
  4. MDN Web Docs — Object.getPrototypeOf()
  5. JavaScript.info — Prototypal inheritance
  6. JavaScript.info — Function prototype