Skip to content

Instantly share code, notes, and snippets.

@noveogroup-amorgunov
Created December 27, 2017 09:52
Show Gist options
  • Save noveogroup-amorgunov/30e915416e9bbe32702ccd7c664a6495 to your computer and use it in GitHub Desktop.
Save noveogroup-amorgunov/30e915416e9bbe32702ccd7c664a6495 to your computer and use it in GitHub Desktop.
Javascript classes ES6

Classes ES6

Прототипы

JS изначально проектировался как очень простой и легкий язык, в нем заложено много концепций, которые делает язык не похожим на другие.

Например, иерархия объектов в JS строиться на основе прототипов и прототипного наследования. Что бы понять как это устроено, нужно уделить довольно много времени, и так как cейчас прототипы при разработке используются очень редко, мы их рассматривать не будем, но вы можете почитать как они работают в онлайн учебнике: learn.javascript

Раньше разработчики с помощью них создавали конструции, подобные классам в других ОО-языках. На слайде пример создая класса с использованием старого синтаксиса, используя прототип и функцию.

function Point(x, y) {
    this.x = x;
    this.y = y;
}
  
Point.prototype.outputPoint = function() {
    console.log(this.x, this.y);
}

const point = new Point(10, 25);
point.outputPoint();  // -> 10, 25

Конструкции class и constructor

Но в стандарте ES6 представили новый синтаксис для классов. Класс ES6 не представляет собой новую объектно-ориентированную модель наследования, это просто синтаксический сахар для существующего в JavaScript прототипного наследования.

Также появился метод constructor, который запускается при создании экземпляра класса

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  outputPoint() {console.log(this.x, this.y);}
}

const point = new Point(10, 25);
point.outputPoint();  // -> 10, 25

Статические свойства классов

В ES6 (ES7) теперь можно объявлять статические свойства класса. К статическим свойствам класса можно обращаться без создания экземпляра. Зачастую в статические свойства записывают константы.

class Point {
  static name = 'SomePoint';
  
  outputName() {
    console.log(Point.name);
  }
}

let point = new Point();
point.outputName();         // -> SomePoint
console.log(Point.name);    // -> SomePoint

Геттеры и сеттеры

В классах, как и в обычных объектах, можно объявлять геттеры и сеттеры через get/set. Но, стоит помнить, class не позволяет задавать свойства-значения

class User {
  constructor({firstName, lastName}) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  // геттер
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }

  // сеттер
  set fullName(newValue) {
    [this.firstName, this.lastName] = newValue.split(' ');
  }
}

let user = new User('Mike', 'Brown');
console.log(user.fullName); // Mike Brown

user.fullName = 'Piter Parker';
console.log(user.fullName); // Piter Parker

Наследование

Для наследования используется директива extends. В примере ниже мы используем директиву super(...), таким образом мы вызываем конструктор родителя и можем туда передать аргументы. Если при наследование у дочернего класса нет метода constructor, то автоматически присвоится конструктор родителя.

class User {
  constructor(name) {
    this.name = name;
  }
  
  whoAmI() {
    console.log( My name is ${this.name} );
  }
}


class Admin extends User {
  constructor(name) {
    super(name);
  }
}

// -> My name is John
new Admin('John').whoAmI(); 

Вызов родительских методов (super)

В ES6 очень удобно стало вызывать родительские методы, раньше необходимо было использовать конструкцию Parent.prototype.method (с использованием прототипа), теперь все стало проще, можно использовать директиву super.

class User {
  constructor(name) {
    this.name = name;
  }
  
  whoAmI() {
    console.log( My name is ${this.name} );
  }
}


class Admin extends User {
  whoAmI() {
    console.log('I\'m admin');
    super.whoAmI();
  }
}
// -> I'm admin\n My name is John
new Admin('John').whoAmI();

Проверка класса с помощью instanceof

Оператор instanceof позволяет проверить, какому классу принадлежит объект, с учетом прототипного наследования. Вызов obj instanceof Constructor возвращает true, если объект принадлежит классу Constructor или классу, наследующему от него.

class Cat() {}

const persik = new Cat(); // создаём объект

// проверяем - этот объект создан Cat?
console.log(persik instanceof Cat); // true, верно

Передача аргументов в конструктор

Если аргументов много, их можно передавать в одном объекте, что дает огромный плюс, не нужно помнить о порядке передачи аргументов и в коде сразу можно понять, какие поля передаются в конструктор (метод) по ключам. Этот подход используется не только для конструкторов, но и для всех функций.

class User {
  constructor(firstName, lastName, language = 'en') {
    this.firstName = firstName;
    this.lastName = lastName;
    this.language = language;
  }
}
const alex = new User('Alex', 'Poter', 'ru');
const tom = new User('Tom', 'Cruise');
class User {
-  constructor(firstName, lastName, language = 'en') {
+  constructor({firstName, lastName, language = 'en'}) {
  }
}

- const alex = new User('Alex', 'Poter', 'ru');
+ const alex = new User({firstName: 'Alex', lastName: 'Poter', language: 'ru'});
  1. Создать класс Cat, который будет принимать в параметрах имя кота, и содержать метод say, который будет возращать сообщение: " says meow". Фраза meow должна хранится как статическая переменная внутри класса.
const persik = new Cat('Persik');
persik.say(); // Persik says meow

const boris = new Cat('Boris');
boris.say(); // Boris says meow
  1. Создать класс Accumulator - аккумулятор значений. Инстансы классы должны хранить текущую сумму в свойстве value (начальное значение устанавливать в конструкторе класса) и прибавлять к ней то, что вводит посетитель. Реализовать метод read(), который будет вызывать метод prompt и результат вызова принимает число и прибавляет его к свойству value.
const accumulator = new Accumulator(1); // начальное значение 1
console.log(accumulator.value); // выведет 1

accumulator.read(); // прибавит ввод prompt к текущему значению
accumulator.read(); // прибавит ввод prompt к текущему значению
console.log(accumulator.value); // выведет текущее значение
  1. Написать класс Clock, объекты которой будут запускать вывод текущего времени в консоль и останавливать вывод. В качестве параметров можно передавать объект options, в котором можно передавать интервал (tickTimeout), через которое выводится время в консоль после предыдущего вывода (по умолчанию интервал должен быть установлен через 1000мс). Для вывода в консоль сообщения через N миллисекунд использовать функцию setInterval, для получения времени - объект Date.

Пример работы в dev tools браузера:

const clock = new Clock({
  tickTimeout: 2000
});

clock.start();

// 15:00:09
// 15:00:11
// 15:00:13
// ...

clock.stop();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment