Тема 2.3 Прототипное наследование
В программирования часто решаются задачи по расширению возможностей определенного кода (модуля). Например, у нас есть объект user со своими свойствами и методами. На его основе нам надо создать объекты admin и guest, как слегка измененные варианты объекта user. Такую возможность нам может предоставить прототипное наследование.
[[Prototype]]
В JavaScript объекты имеют специальное скрытое свойство [[Prototype]], которое либо равно null, либо ссылается на другой объект. Этот объект называется прототип:
Когда мы хотим прочитать свойство из object, а оно отсутствует, JavaScript автоматически берет его из прототипа. Многие возможности языка основываются на прототипном наследовании.
Свойство [[Prototype]] является внутренним и скрытым, но его можно задать:
Одном из способов использования конструкции __proto__, например:
let animal = {
eats: true
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal;
Если мы ищем свойство в rabbit, а оно отсутствует, JavaScript автоматически берет его из animal.
Можно сказать, что animal является прототипом rabbit или rabbit прототипно наследует от animal. Так что если у animal много полезных свойств и методов, то они автоматически становятся доступными у rabbit. Такие свойства называются унаследованными.
let animal = {
eats: true,
walk() {
alert("Animal walk");
}
};
let rabbit = {
jumps: true,
__proto__: animal
};
// walk взят из прототипа
rabbit.walk(); // Animal walk
Прототип используется только для чтения свойств. Операции записи/ удаления работают напрямую с объектом. Присвоим rabbit собственный метод walk:
let animal = {
eats: true,
walk() {
/* этот метод не будет использоваться в rabbit */
}
};
let rabbit = {
__proto__: animal
};
rabbit.walk = function() {
alert("Rabbit! Bounce-bounce!");
};
rabbit.walk(); // Rabbit! Bounce-bounce!
Свойство __proto__ считается устаревшим. На сегодняшний день его заменили методами:
Object.create(proto, [descriptors]) – создает пустой объект со свойством [[Prototype]], указанным как proto, и необязательными дескрипторами свойств descriptors.
Object.getPrototypeOf(obj) – возвращает свойство [[Prototype]] объекта obj.
Object.setPrototypeOf(obj, proto) – устанавливает свойство [[Prototype]] объекта obj как proto.
Рассмотрим на примере:
let animal = {
eats: true
};
// создаём новый объект с прототипом animal
let rabbit = Object.create(animal);
alert(rabbit.eats); // true
// получаем прототип объекта rabbit
alert(Object.getPrototypeOf(rabbit) === animal);
// заменяем прототип объекта rabbit на {}
Object.setPrototypeOf(rabbit, {});
У Object.create есть необязательный второй аргумент. Его можно использовать для добавления дополнительных свойств новому объекту:
let animal = {
eats: true
};
let rabbit = Object.create(animal, {
jumps: {
value: true
}
});
alert(rabbit.jumps); // true
Тема 2.4 Классы
Класс –это расширяемый шаблон кода для создания объектов, который устанавливает в них начальные значения (свойства) и реализацию поведения (методы).
Базовый синтаксис создания класса выглядит следующим образом:
class MyClass {
// методы класса
constructor() { ... }
method1() { ... }
method2() { ... }
method3() { ... }
...
}
Затем используется вызов new MyClass() для создания нового объекта со всеми перечисленными методами. При этом автоматически вызывается метод constructor(), в нем можно инициализировать объект.
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Использование:
let user = new User("Иван");
user.sayHi();
Когда вызывается new User("Иван"):
1. Создается новый объект;
2. Constructor запускается с заданным аргументом и сохраняет его в this.name.
Затем можно вызывать на объекте методы, такие как user.sayHi().
Методы в классе не разделяются запятой!
В JavaScript класс – это разновидность функции. Конструкция class User{…}:
1. Создает функцию с именем User, которая становится результатом объявления класса. Код функции берется из метода constructor;
2. Сохраняет все методы, такие как sayHi, в User.prototype.
При вызове метода объекта new User он будет взят из прототипа. Таким образом, объекты new User имеют доступ к методам класса.
Геттеры/ сеттеры
В классах можно объявлять вычисляемые свойства, геттеры/сеттеры и другие.
Пример user.name, реализованный с использованием get/set:
class User {
constructor(name) {
// вызывает сеттер
this.name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length < 4) {
alert("Имя слишком короткое.");
return;
}
this._name = value;
}
}
let user = new User("Иван");
alert(user.name); // Иван
user = new User(""); // Имя слишком короткое.
Дата добавления: 2021-01-26; просмотров: 372;