}
set gravity(value) {
console.log("Setting value!");
this._gravity = value;
}
get gravity() {
console.log("Getting value!");
return this._gravity;
}
}
let earth = new Planet("Earth", 6378);
earth.gravity = 9.81;
earth.getSurfaceArea();
console.log(earth.gravity) // 9.81
Вот и все. Такое добавление элементов в тело класса хорошо тем, что они не будут существовать в созданном объекте. Вместо этого они будут находиться в прототипе (Planet.prototype), как показано на рис. 20.3.
Рис. 20.3. Нам не нужно делать ничего особенного, чтобы обратиться к объекту-прототипу
Это очень хорошо, так как нам не нужно, чтобы каждый объект без необходимости носил в себе копию содержимого класса, когда с этим прекрасно справляется совместно используемый экземпляр. Наши геттер и сеттер gravity наряду с функцией getSurfaceArea полностью существуют в прототипе.
Почему функции внутри класса выглядят странно?
Вы могли заметить, что функции внутри класса выглядят несколько необычно. К примеру, в них не достает ключевого слова function. Эта странность (в данном случае) не связана с самими классами. Дело в том, что при определении функций внутри объектов можно использовать упрощенный синтаксис.
Вместо написания, например, этого:
let blah = {
zorb: function() {
// что-то интересное
}
};
вы можете сократить определение функции zorb до следующего:
let blah = {
zorb() {
// что-то интересное
}
};
Именно такую сокращенную форму вы будете встречать и использовать при определении функций внутри тела класса.
Расширение объектов
Последнее, что мы рассмотрим, связано с расширением объектов в мире классов. Чтобы разобраться в этой теме, мы будем работать с совершенно новым типом планеты, известным как 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. Если мы хотим просто расширить класс и не нуждаемся в изменении конструктора, то можем полностью пропустить определение конструктора в этом классе: