Понимание объектно-ориентированного программирования (ООП) в JavaScript

Понимание объектно-ориентированного программирования (ООП) в JavaScript

Введение:

Многие разработчики сомневаются, является ли JavaScript функциональным языком программирования или объектно-ориентированным!

На самом деле, он является и тем, и другим!

JavaScript - это прототипно-ориентированный процедурный язык, что означает, что он поддерживает как функциональное, так и объектно-ориентированное программирование.

В этой статье мы изучим и применим концепции объектно-ориентированного программирования (ООП) в JavaScript.

Что такое ООП?

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

Существуют два типа языков ООП:

  1. Языки, основанные на классах.
  2. Языки, основанные на прототипах.

Так что если вы приходите из C++ или Java, вам знакомы с синтаксисами, основанными на классах.

Но JavaScript - это язык программирования, основанный на прототипах!

💡 Примечание: Прототипы - это механизм, с помощью которого объекты JavaScript наследуют функции друг у друга. ~ Документы MDN

4 основных принципа ООП:

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

Абстракция

Инкапсуляция

Полиморфизм

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

Имеет ли JavaScript классы?

Да и нет!

Как так?

Запутанно, верно?

Позвольте мне объяснить это!

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

Но подождите!

JavaScript поддерживает ключевое слово Class!

”Ключевое слово class в JavaScript на самом деле является синтаксическим сахаром над наследованием, основанным на прототипах, которое уже существует и поддерживается в JavaScript.”

Несмотря на то, что оно позволяет нам использовать ключевое слово class, внутри оно использует свой механизм, основанный на прототипах. Это сделано для помощи разработчикам, приходящим из языков, основанных на классах, таких как C++ и Java.

Объектный литерал:

Это способ определения объекта с использованием простого и краткого синтаксиса. Он позволяет создавать объект без использования традиционного синтаксиса конструктора или метода Object.create().

Давайте разберемся на примерах,

До появления объектных литералов мы создавали объекты с использованием метода Object.create(), что было не очень эффективно.

const personPrototype = {
	greet: function () {
		console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
	},
};

const person = Object.create(personPrototype);
person.name = 'Arindam';
person.age = 18;
person.isStudent = true;

Здесь вы можете видеть, что код слишком длинный!

В то время как с использованием объектных литералов вы можете легко написать ту же программу следующим образом:

const person = {
	name: 'Arindam',
	age: 18,
	isStudent: true,
	greet() {
		console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
	},
};
person.greet(); // Output: Hello, my name is Arindam and I'm 18 years old.

Ключевое слово «this»:

Вы заметили, что в предыдущем коде мы использовали this.name вместо просто name.

Но почему?

Каково значение ключевого слова “this”?

Давайте разберемся с этим на примерах,

Сначала мы удалим ключевое слово this из кода и посмотрим, что произойдет.

const person = {
	name: 'Arindam',
	age: 18,
	isStudent: true,
	greet() {
		console.log(`${name}`);
	},
};
person.greet(); // output:undefined

Эта программа выводит undefined!

Но почему? Ведь мы уже определили переменную name в функции!

Это происходит потому, что функция greet не имеет переменной с именем name. Когда мы попытались получить доступ к свойству name, JavaScript искал его в области видимости функции (в данном случае, в области видимости функции greet) и вернул undefined.

Чтобы правильно получить доступ к свойству name объекта person внутри метода greet, вам нужно использовать ключевое слово this. Ключевое слово this ссылается на текущий объект (в данном случае, на объект person), на котором вызывается метод.

Вот более техническое определение ключевого слова ‘this’:

Ключевое слово this в JavaScript ссылается на контекст, в котором выполняется функция.

Ключевое слово 'new':

”Ключевое слово new в JavaScript используется для создания экземпляров объектов с помощью конструкторных функций. Оно играет важную роль в объектно-ориентированном программировании, так как облегчает процесс создания объектов с определенными свойствами и поведением.”

Не поняли? Не волнуйтесь!

Давайте разберемся с этим на примерах.

function User(username, age) {
	this.username = username;
	this.age = age;
	return this.name;
}
const User1 = User(Arindam, 18);
console.log(User1); //output: Arindam

Здесь мы создали функцию с именем User, которая возвращает свойство name. Затем создали User1.

И вывод такой же, как мы предсказывали.

Теперь создадим еще одного пользователя и посмотрим, что произойдет.

function User(username, age) {
	this.username = username;
	this.age = age;
	return this.name;
}
const User1 = User(Arindam, 18);
const User2 = User(Diya, 17);
console.log(User1); //Output: Diya

Здесь мы создали еще одного пользователя (здесь это User2) и вывели предыдущего пользователя (здесь это User1).

Но подождите! Вывод не такой, как раньше!

User2 перезаписал значение User1. Как вы понимаете, это серьезная проблема. Чтобы решить эту проблему, мы используем ключевое слово new.

Теперь давайте сделаем то же самое с ключевым словом new и посмотрим, что произойдет:

function User(username, age) {
	this.username = username;
	this.age = age;
	return this.name;
}
const User1 = new User(Arindam, 18);
const User2 = new User(Diya, 17);
console.log(User1); //Output: Arindam

Здесь ключевое слово new создает экземпляры конструкторной функции (в данном случае это User). Поэтому у нас есть две копии/экземпляра функции, и нет никакой возможности перезаписать данные.

💡 Примечание: Использование ключевого слова new с обычной функцией (не конструкторной функцией) не создаст новый экземпляр и может вызвать непредвиденное поведение или ошибки. Ключевое слово new используется специально с конструкторными функциями для создания и инициализации экземпляров объектов.

Внутренняя работа new:

Когда вы используете ключевое слово new с конструкторной функцией, происходят следующие шаги:

  1. Создается новый пустой объект. Этот новый объект становится экземпляром конструкторной функции.
  2. Ключевое слово this внутри конструкторной функции устанавливается на вновь созданный объект. Это позволяет конструкторной функции ссылаться и устанавливать свойства на вновь созданном экземпляре.
  3. Выполняется конструкторная функция, и любые свойства или методы, определенные с помощью ключевого слова this внутри конструктора, добавляются к новому экземпляру.
  4. Если конструкторная функция не возвращает явно объект, новый экземпляр, созданный с помощью new, возвращается в качестве результата нового выражения. Это позволяет вам сохранить созданный экземпляр в переменной и использовать его позже.

Спасибо за чтение :)