JavaScript с нуля
- Автор: Кирупа Чиннатамби
- Жанр: Образование
- Дата выхода: 2021
- Цикл: Библиотека программиста
Читать книгу "JavaScript с нуля"
Расширение объектов
Последнее, что мы рассмотрим, связано с расширением объектов в мире классов. Чтобы разобраться в этой теме, мы будем работать с совершенно новым типом планеты, известным как Potato Planet (планета Картофель).
Планета Картофель содержит все, что присуще обычной планете, но состоит она полностью из картофеля, в противоположность расплавленным камням и газу, составляющим другие виды планет. Наша задача определить планету Картофель как класс. Ее функциональность будет, по большому счету, отражать представленную в классе Planet, но мы также добавим некоторые дополнительные элементы вроде аргумента potatoType в конструкторе и метода getPotatoType, выводящего в консоль значение potatoType.
Не самым лучшим подходом было бы определить класс Картофеля так:
class PotatoPlanet {
constructor(name, radius, potatoType) {
this.name = name;
this.radius = radius;
this.potatoType = potatoType;
}
getSurfaceArea() {
let surfaceArea = 4 * Math.PI * Math.pow(this.radius, 2);
console.log(surfaceArea + " square km!");
return surfaceArea;
}
getPotatoType() {
var thePotato = this.potatoType.toUpperCase() +"!!1!!!";
console.log(thePotato);
return thePotato;
}
set gravity(value) {
console.log("Setting value!");
this._gravity = value;
}
get gravity() {
return this._gravity;
}
}
У нас есть класс PotatoPlanet, и он содержит не только новые связанные с Картофелем элементы, но также всю функциональность класса Planet. Плохо в этом подходе то, что мы повторяем код. А что, если бы вместо повторения кода у нас была возможность расширить функциональность, предоставляемую нашим классом Planet, функциональностью, необходимой для PotatoPlanet? Такой подход будет однозначно лучше. К счастью, эта возможность у нас есть, и предоставлена она в виде ключевого слова extends. Расширив класс Planet классом PotatoPlanet, мы можем сделать следующее:
class Planet {
constructor(name, radius) {
this.name = name;
this.radius = radius;
}
getSurfaceArea() {
let surfaceArea = 4 * Math.PI * Math.pow(this.radius, 2);
console.log(surfaceArea + " square km!");
return surfaceArea;
}
set gravity(value) {
console.log("Setting value!");
this._gravity = value;
}
get gravity() {
return this._gravity;
}
}
class PotatoPlanet extends Planet {
constructor(name, width, potatoType) {
super(name, width);
this.potatoType = potatoType;
}
getPotatoType() {
let thePotato = this.potatoType.toUpperCase() +"!!1!!!";
console.log(thePotato);
return thePotato;
}
}
Обратите внимание, как мы объявляем класс PotatoPlanet — используем ключевое слово extends и указываем класс, который расширяем, то есть Planet:
class PotatoPlanet extends Planet {
.
.
.
.
}
Здесь нужно помнить кое-что, связанное с constructor. Если мы хотим просто расширить класс и не нуждаемся в изменении конструктора, то можем полностью пропустить определение конструктора в этом классе:
class PotatoPlanet extends Planet {
sayHello() {
console.log("Hello!");
}
}
В нашем же случае, поскольку мы изменяем действия конструктора, добавляя свойство для типа картошки, то мы снова определяем его с одним важным дополнением:
class PotatoPlanet extends Planet {
constructor(name, width) {
super(name, width);
this.potatoType = potatoType;
}
getPotatoType() {
var thePotato = this.potatoType.toUpperCase() +"!!1!!!";
console.log(thePotato);
return thePotato;
}
}
Мы производим явный вызов конструктора родителя (Planet) с помощью ключевого слова super и передачи соответствующих необходимых аргументов. Вызов super обеспечивает срабатывание всей необходимой функциональности части Planet нашего объекта.
Чтобы использовать PotatoPlanet, мы создаем объект и заполняем его свойства или вызываем для него методы так же, как и в случае с простым, не расширенным объектом. Вот пример создания объекта типа PotatoPlanet с именем spudnik:
let spudnik = new PotatoPlanet("Spudnik", 12411, "Russet");
spudnik.gravity = 42.1;
spudnik.getPotatoType();
При этом хорошо то, что spudnik имеет доступ не только к функциональности, определенной нами как часть класса PotatoPlanet, но и всей функциональности, предоставляемой классом Planet, который мы расширяем. Мы можем понять, почему это происходит, еще раз обратившись к нашим прототип-объектным связям (рис. 20.4).
Рис. 20.4. Так выглядит расширение объекта
Если мы проследуем по цепочке прототипов, то от объекта spudnik перейдем к PotatoPlanet.prototype, оттуда — к Planet.prototype, а закончим в Object.prototype. Объект spudnik имеет доступ к любому свойству или методу, определенному в каждом этом прототипе, что и дает ему возможность вызывать эти элементы для Object или Planet, несмотря на то что большая их часть не определена в PotatoPlanet. В этом заключается удивительная мощь расширения объектов.
КОРОТКО О ГЛАВНОМ
Синтаксис класса значительно упрощает работу с объектами. Вы можете уловить отголоски этого в текущей главе, но главное вы увидите позднее. Суть этого синтаксиса в том, что он позволяет нам больше фокусироваться на том,
Есть вопросы? Не откладывайте. Обращайтесь на форум https://forum.kirupa.com.