Обзор
В ES6 class (класс) введён как шаблон для объектов, и классы можно определять с помощью ключевого слова class.
По сути, class — это функция.
Это можно рассматривать как синтаксический сахар, делающий синтаксис прототипов объектов более ясным и более похожим на синтаксис объектно-ориентированного программирования.
Базовое использование
Определение класса
Выражения класса могут быть анонимными или именованными.
let Example = class {
constructor(a) {
this.a = a;
}
}
let Example = class Example {
constructor(a) {
this.a = a;
}
}
Объявление класса
class Example {
constructor(a) {
this.a = a;
}
}
Важное примечание: нельзя повторно объявить.
class Example{}
class Example{}
let Example1 = class{}
class Example{}
Важные замечания
Определения классов не поднимаются, поэтому класс нужно определить до обращения к нему, иначе будет выброшена ошибка.
Методы в классе не требуют ключевого слова function.
Точки с запятой нельзя добавлять между методами.
new Example();
class Example {}
Тело класса
Свойства
prototype
В ES6 prototype всё ещё существует. Хотя методы можно определять непосредственно в классе, на самом деле они всё ещё определяются на prototype.
Переопределение методов / Добавление методов во время инициализации
Добавление методов
Object.assign(Example.prototype,{
})
Статические свойства
Статические свойства: свойства самого класса, т.е. свойства, определённые непосредственно внутри класса (Class.propname), которые не требуют создания экземпляра.
В ES6 указано, что класс имеет только статические методы, но не статические свойства.
class Example {
static a = 2;
}
Пример.b = 2;
Публичные свойства
class Example{}
Example.prototype.a = 2;
Свойства экземпляра
Свойства экземпляра: свойства, определённые на объекте экземпляра (this).
class Example {
a = 2;
constructor () {
console.log(this.a);
}
}
свойство name
Возвращает имя класса, следующее за class (если присутствует).
let Example=class Exam {
constructor(a) {
this.a = a;
}
}
console.log(Example.name);
let Example=class {
constructor(a) {
this.a = a;
}
}
console.log(Example.name);
Методы
метод constructor
Метод constructor — это метод класса по умолчанию, вызываемый при создании объекта-экземпляра класса.
class Example{
constructor(){
console.log('Я конструктор');
}
}
new Example();
Возвращаемый объект
class Test {
constructor(){
}
}
console.log(new Test() instanceof Test);
class Example {
constructor(){
return new Test();
}
}
console.log(new Example() instanceof Example);
Статические методы
class Example{
static sum(a, b) {
console.log(a+b);
}
}
Example.sum(1, 2);
Методы прототипа
class Example {
sum(a, b) {
console.log(a + b);
}
}
let exam = new Example();
exam.sum(1, 2);
Методы экземпляра
class Example {
constructor() {
this.sum = (a, b) => {
console.log(a + b);
}
}
}
Создание экземпляра класса
новый
Для создания экземпляра класса необходимо использовать ключевое слово new.
class Example {}
let exam1 = Example();
Созданный объект
Общий объект-прототип
class Example {
constructor(a, b) {
this.a = a;
this.b = b;
console.log('Example');
}
sum() {
return this.a + this.b;
}
}
let exam1 = new Example(2, 1);
let exam2 = new Example(3, 1);
console.log(Object.getPrototypeOf(exam1) === Object.getPrototypeOf(exam2));
Object.getPrototypeOf(exam1).sub = function() {
return this.a - this.b;
}
console.log(exam1.sub());
console.log(exam2.sub());
декоратор
Декоратор — это функция, используемая для изменения поведения класса, вступающая в силу во время компиляции кода.
Декоратор класса
Один параметр
Первый параметр, target, указывает на сам класс.
function testable(target) {
target.isTestable = true;
}
@testable
class Example {}
Example.isTestable;
Несколько параметров — вложенная реализация
function testable(isTestable) {
return function(target) {
target.isTestable=isTestable;
}
}
@testable(true)
class Example {}
Example.isTestable;
Свойства экземпляра
Два примера выше добавляют статические свойства. Чтобы добавить свойства экземпляра, просто работайте с прототипом класса.
Декоратор метода
Три параметра: target (объект-прототип класса), name (имя изменяемого свойства), descriptor (объект дескриптора свойства).
class Example {
@writable
sum(a, b) {
return a + b;
}
}
function writable(target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
Порядок выполнения декораторов
Входит снаружи внутрь, выполняется изнутри наружу.
class Example {
@logMethod(1)
@logMethod(2)
sum(a, b){
return a + b;
}
}
function logMethod(id) {
console.log('вычислен logMethod'+id);
return (target, name, desctiptor) => console.log('выполнен logMethod '+id);
}
Инкапсуляция и наследование
геттер / сеттер
Определение
class Example{
constructor(a, b) {
this.a = a;
this.b = b;
}
get a(){
console.log('getter');
return this.a;
}
set a(a){
console.log('setter');
this.a = a;
}
}
let exam = new Example(1,2);
class Example1{
constructor(a, b) {
this.a = a;
this.b = b;
}
get a(){
console.log('getter');
return this._a;
}
set a(a){
console.log('setter');
this._a = a;
}
}
let exam1 = new Example1(1,2);
console.log(exam1._a);
геттер не может использоваться отдельно
class Example {
constructor(a) {
this.a = a;
}
get a() {
return this.a;
}
}
let exam = new Example(1);
геттер и сеттер должны находиться на одном уровне
class Father {
constructor(){}
get a() {
return this._a;
}
}
class Child extends Father {
constructor(){
super();
}
set a(a) {
this._a = a;
}
}
let test = new Child();
test.a = 2;
console.log(test.a);
class Father1 {
constructor(){}
get a() {
return this._a;
}
set a(a) {
this._a = a;
}
}
class Child1 extends Father1 {
constructor(){
super();
}
}
let test1 = new Child1();
test1.a = 2;
console.log(test1.a);
extends
Наследование классов реализуется через extends.
class Child extends Father { ... }
super
Метод конструктора подкласса должен содержать super, и он должен стоять перед this.
class Father {
constructor() {}
}
class Child extends Father {
constructor() {}
}
let test = new Child();
Вызов конструктора родительского класса может находиться только в конструкторе подкласса.
class Father {
test(){
return 0;
}
static test1(){
return 1;
}
}
class Child extends Father {
constructor(){
super();
}
}
class Child1 extends Father {
test2() {
super();
}
}
Вызов методов родительского класса: super как объект указывает на объект-прототип родительского класса в обычных методах и на родительский класс в статических методах.
class Child2 extends Father {
constructor(){
super();
console.log(super.test());
}
static test3(){
return super.test1+2;
}
}
Child2.test3();
Важные замечания
Невозможно наследовать обычные объекты.
var Father = {
}
class Child extends Father {
}
Object.setPrototypeOf(Child.prototype, Father);