Выбрать главу

}

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. Если мы хотим просто расширить класс и не нуждаемся в изменении конструктора, то можем полностью пропустить определение конструктора в этом классе: