Объектно-ориентированное программирование

Последнее обновление: 25.10.2023

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

Объекты

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

Для работы с подобными структурами в JavaScript используются объекты. Каждый объект может хранить свойства, которые описывают его состояние, и методы, которые описывают его поведение

Создание нового объекта

Есть несколько способов создания нового объекта.

Первый способ заключается в использовании конструктора Object:

const user = new Object();

В данном случае объект называется user.

Выражение new Object() представляет вызов конструктора - функции, создающей новый объект. Для вызова конструктора применяется оператор new. Вызов конструктора фактически напоминает вызов обычной функции.

Второй способ создания объекта представляет использование фигурных скобок (литеральная нотация):

const user = {};

На сегодняшний день более распространенным является второй способ.

Свойства объекта

После создания объекта мы можем определить в нем свойства. Чтобы определить свойство, надо после названия объекта через точку указать имя свойства и присвоить ему значение:

const user = {};
user.name = "Tom";
user.age = 26;

В данном случае объявляются два свойства name и age, которым присваиваются соответствующие значения. После этого мы можем использовать эти свойства, например, вывести их значения в консоли:

console.log(user.name);
console.log(user.age);

Также можно определить свойства при определении объекта:

const user = {
 
    name: "Tom",
    age: 26
};

В этом случае для присвоения значения свойству используется символ двоеточия, а после определения свойства ставится запятая (а не точка с запятой).

Кроме того, доступен сокращенный способ определения свойств:

const name = "Tom";
const age = 34;
const user = {name, age};
console.log(user.name);		// Tom
console.log(user.age);		// 34

В данном случае названия переменных также являются и названиями свойств объекта. И таким образом можно создавать более сложные конструкции:

const name = "Tom";
const age = 34;
const user = {name, age};

const teacher = {user, course: "JavaScript"};
console.log(teacher.user);		// {name: "Tom", age: 34}
console.log(teacher.course);	// JavaScript

Методы объекта

Методы объекта определяют его поведение или действия, которые он производит. Методы представляют собой функции. Например, определим метод, который бы выводил имя и возраст человека:

const user = {};
user.name = "Tom";
user.age = 26;
user.display = function(){
	
	console.log(user.name);
	console.log(user.age);
};

// вызов метода
user.display();

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

Также методы могут определяться непосредственно при определении объекта:

const user = {
 
    name: "Tom",
    age: 26,
    display: function(){
     
        console.log(this.name);
        console.log(this.age);
    }
};

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

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

Также можно использовать сокращенный способ определения методов, когда двоеточие и слово function опускаются:

let user = {
 
    name: "Tom",
    age: 26,
    display(){
     
        console.log(this.name, this.age);
    },
	move(place){
		console.log(this.name, "goes to", place);
	}
};
user.display();	// Tom 26
user.move("the shop");	// Tom goes to the shop

Синтаксис массивов

Существует также альтернативный способ определения свойств и методов с помощью синтаксиса массивов:

const user = {};
user["name"] = "Tom";
user["age"] = 26;
user["display"] = function(){
	
	console.log(user.name);
	console.log(user.age);
};

// вызов метода
user["display"]();

Название каждого свойства или метода заключается в кавычки и в квадратные скобки, затем им также присваивается значение. Например, user["age"] = 26.

При обращении к этим свойствам и методам можно использовать либо нотацию точки (user.name), либо обращаться так: user["name"]

Также можно определить свойства и методы через синтаксис массивов напрямую при создании объекта:

const user = {
	["name"]: "Tom",
	["age"]: 26,
	["display"]: function(){
     
		console.log(user.name);
		console.log(user.age);
	}
};
user["display"]();

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

Также следует отметить, что названия свойств и методов объекта всегда представляют строки. То есть мы могли предыдущее определение объекта переписать так:

const user = {
	"name": "Tom",
	"age": 26,
	"display": function(){
	
		console.log(user.name);
		console.log(user.age);
	}
};
// вызов метода
user.display();

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

const user = {
	name: "Tom",
	age: 26,
	"full name": "Tom Johns",
	"display info": function(){
	
		console.log(user.name);
		console.log(user.age);
	}
};
console.log(user["full name"]);
user["display info"]();

Только в этом случае для обращении к подобным свойствам и методам мы должны использовать синтаксис массивов.

Динамическое определение имен свойств и методов

Синтаксис массивов открывает нам другую возможность - определение имени свойства вне объекта:

const prop1  = "name";
const prop2  = "age";
const tom = { 
	[prop1]: "Tom",
	[prop2]: 37
};
console.log(tom);			// {name: "Tom", age: 37}
console.log(tom.name);		// Tom
console.log(tom["age"]);	// 37

Благодая этому, например, можно динамически создавать объекты с произвольными названиями свойств:

function createObject(propName, propValue){
	return {
			[propName]: propValue,
			print(){ 
				console.log(`${propName}: ${propValue}`);
			}
	};
}
const person = createObject("name", "Tom");
person.print();		// name: Tom

const book = createObject("title", "JavaScript Reference");
book.print();	// title: JavaScript Reference

Удаление свойств

Выше мы посмотрели, как можно динамически добавлять новые свойства к объекту. Однако также мы можем удалять свойства и методы с помощью оператора delete. И как и в случае с добавлением мы можем удалять свойства двумя способами. Первый способ - использование нотации точки:

delete объект.свойство

Либо использовать синтаксис массивов:

delete объект["свойство"]

Например, удалим свойство:

let user = {};
user.name = "Tom";
user.age = 26;
user.display = function(){
	
	console.log(user.name);
	console.log(user.age);
};

console.log(user.name); // Tom
delete user.name; // удаляем свойство
// альтернативный вариант
// delete user["name"];
console.log(user.name); // undefined

После удаления свойство будет не определено, поэтому при попытке обращения к нему, программа вернет значение undefined.

Создание объекта из переменных и констант

При создании объекта его свойствам могут передаваться значения переменных, констант или динамически вычисляемые результаты функций:

function getSalary(status){
	if(status==="senior") return 1500;
	else return 500;
}
const name = "Tom";
const age = 37;
const person = { name: name, age: age, salary: getSalary()};

console.log(person);	// {name: "Tom", age: 37, salary: 500}

Но если названия констант/переменных совпадает с названиями свойств, то можно сократить передачу значений:

const name = "Tom";
const age = 37;
const salary = 500;
const person = { name, age, salary};

console.log(person);	// {name: "Tom", age: 37, salary: 500}

В данном случае объект person автоматически получит свойства, названия которых будут соответствовать названиям констант, а в качестве значений иметь значения этих констант.

То же самое относится к передаче функций методам объекта:

function display(){ 
	console.log(this.name, this.age);
}
const move = function(place){ console.log(this.name, "goes to", place)};
const name = "Tom";
const age = 37;
const salary = 500;
const person = { name, age, salary, display, move};

person.display();		// Tom 37
person.move("cinema");	// Tom goes to cinema

В данном случае объект person имеет два метода, которые соответствуют переданным в объект функциям - display() и move(). Стоит отметить, что при такой передаче функций методам объекта, мы по прежнему можем использовать в этих функциях ключевое слово this для обращения к функциональности объекта. Однако стоит быть осторожным при передаче лямбд-выражений, поскольку для глобальных лямбд-выражений this будет представлять объект окна браузера:

const move = (place)=>{ console.log(this.name, "goes to", place); console.log(this);};
const name = "Tom";

const person = { name, move};
person.move("cinema");	//  goes to cinema

Фукция Object.fromEntries()

С помощью функции Object.fromEntries() можно создать объект из набора пар ключ-значение, где ключ потом будет представляет название свойства. Например, создадим объект из массивов:

const personData = [ ["name", "Tom"], ["age", 37]];
const person = Object.fromEntries(personData);
console.log(person);		// {name: "Tom", age: 37}
console.log(person.name);	 // Tom

Здесь объект создается из массива personData, который содержит два подмассива. Каждый подмассив содержит два элемента и фактически представляет пару ключ-значение. Первый элемент представляет ключ, а второй - значение.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850