DevGang
Авторизоваться

Понимание парадигмы ООП в JavaScript

В этом посте мы исследуем парадигму объектно-ориентированного программирования в JavaScript. ООП - это парадигма, в которой все управляется с помощью объектов.

В JavaScript есть четыре способа работы с объектами:

  1. Фаюричный способ создания объектов.
  2. Прототипный способ создания объектов.
  3. Псевдоклассическая схема создания объектов.
  4. Классы

Лучший способ работать с объектами - это классы. Мы узнаем, как именно работают классы. Давайте рассмотрим каждый метод один за другим.

Фаюричный способ создания объектов

Допустим, нам нужно создать объект с несколькими студентами. С фабричным способом нам не нужно вручную создавать объекты для всех из них. Создаем функцию-конструктор.

function creteStudent(name, batch, marks, maxMarks) {
    let obj = {};
    obj.name = name;
    obj.batch = batch;
    obj.marks = marks;
    obj.maxMarks = maxMarks;
    obj.percentage = function() {
        return `${(marks*100)/maxMarks}%`;
    };

    return obj;
}

Затем, когда нам нужно создать ученика, нам просто нужно вызвать указанную выше функцию.

let student1 = createStudent("Swastik", 9, 95, 100);
let student2 = createStudent("Rahul", 8, 90, 100);

student1.percentage() // 95%

Прототипный способ создания объектов

Когда свойство не найдено в объекте, оно ищет его в цепочке прототипов. Это прототипная природа объекта.

Теперь создадим объект с помощью прототипа.

  1. Создайте объект с помощью Object.create().
  2. Обязательно используйте это в методе.
  3. Не забудьте вернуть объект.
let studentMethod = {
  percentage: function() {
    return `${this.marks*100 / this.maxMarks}%`;
  }
}

function createStudent(name, batch, marks, maxMarks) {
  let obj = Object.create(studentMethod);
  obj.name = name;
  obj.batch = batch;
  obj.marks = marks;
  obj.maxMarks = maxMarks;

  return obj;
}

let student1 = createStudent("Swastik", 9, 99, 100);
student1.percentage(); // 99%

Object.create принимает объект в качестве параметра и помещает этот параметр в dunder-proto. Например, в приведенном выше фрагменте кода процентный метод добавлен в dunder proto, а не в основном объекте.

Псевдоклассический паттерн создания объектов

Псевдоклассический шаблон использует ключевое слово new с функцией конструктора для создания объектов. Новое ключевое слово выполняет 3 функции.

  1. Неявно создает новый объект с именем this.
  2. Помещает новый объект (this) в прототип функции.
  3. Неявно возвращает obj (this).

Когда мы используем ключевое слово new, методы из прототипа переходят в dunder-proto.

  1. this = {}
  2. this.proto = createStudent.prototype
  3. return obj (this)

Например:

function CreateStudent(name, batch, marks, maxMarks) {
  this.name = name;
  this.batch = batch;
  this.marks = marks;
  this.maxMarks = maxMarks;
}

CreateStudent.prototype = {
  percentage: function() {
    return `${this.marks*100 / this.maxMarks}%`;
  }
}

let student1 = new CreateStudent("Swastik", 9, 100, 100);
student1.percentage(); // 100%

Ключевое слово new неявно создает объект, задает метод для dunder-proto и неявно возвращает объект.

Классы

Классы - это синтаксический сахар для создания объектов. В последнем примере мы вручную добавили процентный метод в CreateStudent.prototype. С классами все это происходит автоматически.

  1. Ключевое слово new вызывает конструктор и неявно создает и возвращает этот объект.
  2. Классы принимают только методы (функции).
  3. Вы найдете методы в dunder-proto объекта.

Для instace:

class CreateStudent {
  constructor(name, batch, marks, maxMarks) {
    this.name = name;
    this.batch = batch;
    this.marks = marks;
    this.maxMarks = maxMarks;
  }

  percentage() {
    return `${this.marks*100 / this.maxMarks}%`;
  }
}

let student1 = new CreateStudent("Swastik", 9, 89, 100);
student1.percentage(); // 89%
student1.percentage === CreateStudent.prototype.percentage; // true

Итак, вот как мы создаем объекты с классами. Флаг перечислимости для методов класса по умолчанию установлен в значение false, потому что мы не хотим, чтобы методы были включены в результат цикла for ... in.

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

Наследование классов - это способ создания новой функциональности поверх существующей. Допустим, у нас есть класс Animal и класс Rabbit, основанный на классе Animal.

// Animal Class
class Animal {
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }

  run(speed) {
    this.speed = speed;
    alert(`${this.name} runs with speed ${this.speed}.`);
  }

  stop() {
    this.speed = 0;
    alert(`${this.name} stands still.`);
  }
}

let animal = new Animal("My animal");

// Rabbit Class
class Rabbit extends Animal {
  hide() {
    alert(`${this.name} hides!`);
  }
}

let rabbit = new Rabbit("White Rabbit");

rabbit.run(5); // White Rabbit runs with speed 5.
rabbit.hide(); // White Rabbit hides!

У класса Rabbit нет метода запуска, но он может получить к нему доступ из Animal.prototype, поскольку у нас есть расширенный класс Rabbit.

Ключевое слово Super

Ключевое слово super позволяет нам вызывать родительский метод и конструктор в нашем расширенном классе.

  1. super.method(...) вызывает родительский метод.
  2. super(...) вызывает родительский конструктор.

Например:

class Rabbit extends Animal {
  constructor() {
    super(); // calls the parent constructor
  }

  hide() {
    alert(`${this.name} hides`);
  }

  stop() {
    super.stop(); // calls stop method of parent
    this.hide()
  }
}

let rabbit = new Rabbit("White Rabbit");

rabbit.run(5); // White Rabbit runs with speed 5.
rabbit.stop(); // White Rabbit stands still. White Rabbit hides!

В приведенном выше фрагменте кода класс Rabbit определяет метод остановки, который вызывает метод остановки Animal с помощью super.

Статический метод

Мы также можем назначить метод самому классу, а не его «прототипу». Такие методы называются статическими методами. К ним добавляется ключевое слово static.

class User {
  static staticMethod() {
    console.log(this === User);
  }
}

User.staticMethod(); // true

Статические методы используются для функциональности, относящейся к классу «в целом». Это не относится к конкретному экземпляру класса.

Статические свойства и методы наследуются. Для класса B расширяет прототип класса B само по себе указывает на: В[[Prototype]] = A . Таким образом, если поле не найдено в B, поиск продолжается в A.

Частные и защищенные свойства и методы

  1. Защищенные поля начинаются с _. Защищенное поле должно быть доступно только его классу и классам, унаследованным от него. Защищенное поле не поддерживается на уровне языка.
  2. Частные поля начинаются с символа #. Частное поле должно быть доступно только изнутри класса.
class CoffeeMachine {
    #waterAmount = 0;

    set waterAmount(value) {
        if (value < 0) {
            value = 0;
        }
        this.#waterAmount = value;
    }

    get waterAmount() {
        return this.#waterAmount;
    }

    constructor(power) {
        this.power = power;
    }
}

let coffeeMachine1 = new CoffeeMachine(100);
coffeeMachine1.#waterAmount; // Error - Private method cannot be accessed outside of the class.
coffeeMachine1.waterAmount; // 0;
coffeeMachine1.waterAmount = -20;
coffeeMachine1.waterAmount; // 0;

Приватный метод #waterAmount доступен только внутри самого класса.

Ключевое слово this

Это ключевое слово относится к объекту, которому он принадлежит. Есть четыре правила, чтобы определить, на что ссылается ключевое слово this.

  1. fn() -> window
  2. obj.fn() -> this относится к obj. Если какая-либо функция использует this, то он становится объектом слева от (.).
  3. bind, call, apply -> указанное значение "this".
  4. Ключевое слово new создает и возвращает неявно this.
#JavaScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

В подарок 100$ на счет при регистрации

Получить