Объекты обычно создаются, чтобы представлять сущности реального мира, будь то пользователи, заказы и так далее:
// Объект пользователя
let user = {
name: "Джон",
age: 30
};
И так же, как и в реальном мире, пользователь может совершать действия: выбирать что-то из корзины покупок, авторизовываться, выходить из системы, оплачивать и т.п.
Такие действия в JavaScript представлены свойствами-функциями объекта.
Примеры методов
Для начала давайте научим нашего пользователя user
здороваться:
let user = {
name: "Джон",
age: 30
};
user.sayHi = function() {
alert("Привет!");
};
user.sayHi(); // Привет!
Здесь мы просто использовали Function Expression (функциональное выражение), чтобы создать функцию для приветствия, и присвоили её свойству user.sayHi
нашего объекта.
Затем мы вызвали её. Теперь пользователь может говорить!
Функцию, которая является свойством объекта, называют методом этого объекта.
Итак, мы получили метод sayHi
объекта user
.
Конечно, мы могли бы заранее объявить функцию и использовать её в качестве метода, примерно так:
let user = {
// ...
};
// сначала объявляем
function sayHi() {
alert("Привет!");
};
// затем добавляем в качестве метода
user.sayHi = sayHi;
user.sayHi(); // Привет!
Объектно-ориентированное программирование
Когда мы пишем наш код, используя объекты для представления сущностей реального мира, – это называется объектно-ориентированное программирование или сокращённо: «ООП».
ООП является большой предметной областью и интересной наукой само по себе. Как выбрать правильные сущности? Как организовать взаимодействие между ними? Это – создание архитектуры, и есть хорошие книги по этой теме, такие как «Приёмы объектно-ориентированного проектирования. Паттерны проектирования» авторов Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес или «Объектно-ориентированный анализ и проектирование с примерами приложений» Гради Буча, а также ещё множество других книг.
Сокращённая запись метода
Существует более короткий синтаксис для методов в литерале объекта:
// эти объекты делают одно и то же (одинаковые методы)
user = {
sayHi: function() {
alert("Привет");
}
};
// сокращённая запись выглядит лучше, не так ли?
user = {
sayHi() { // то же самое, что и "sayHi: function()"
alert("Привет");
}
};
Как было показано, мы можем пропустить ключевое слово "function"
и просто написать sayHi()
.
Нужно отметить, что эти две записи не полностью эквивалентны. Есть тонкие различия, связанные с наследованием объектов (что будет рассмотрено позже), но на данном этапе изучения это неважно. В большинстве случаев сокращённый синтаксис предпочтителен.
Ключевое слово «this» в методах
Как правило, методу объекта необходим доступ к информации, которая хранится в объекте, чтобы выполнить с ней какие-либо действия (в соответствии с назначением метода).
Например, коду внутри user.sayHi()
может понадобиться имя пользователя, которое хранится в объекте user
.
Для доступа к информации внутри объекта метод может использовать ключевое слово this
.
Значение this
– это объект «перед точкой», который использовался для вызова метода.
Например:
let user = {
name: "Джон",
age: 30,
sayHi() {
// this - это "текущий объект"
alert(this.name);
}
};
user.sayHi(); // Джон
Здесь во время выполнения кода user.sayHi()
значением this
будет являться user
(ссылка на объект user
).
Технически также возможно получить доступ к объекту без ключевого слова this
, ссылаясь на него через внешнюю переменную (в которой хранится ссылка на этот объект):
let user = {
name: "Джон",
age: 30,
sayHi() {
alert(user.name); // используем переменную "user" вместо ключевого слова "this"
}
};
…Но такой код будет ненадёжным. Если мы решим скопировать ссылку на объект user
в другую переменную, например, admin = user
, и перезапишем переменную user
чем-то другим, тогда будет осуществлён доступ к неправильному объекту при вызове метода из admin
.
Это показано ниже:
let user = {
name: "Джон",
age: 30,
sayHi() {
alert( user.name ); // приведёт к ошибке
}
};
let admin = user;
user = null; // обнулим переменную для наглядности, теперь она не хранит ссылку на объект.
admin.sayHi(); // Ошибка! Внутри sayHi() используется user, которая больше не ссылается на объект!
Если мы используем this.name
вместо user.name
внутри alert
, тогда этот код будет работать.