Роль this в JavaScript
В JavaScript ключевое слово this
имеет решающее значение для обеспечения работы функций в определенном контексте. Чтобы эффективно определить контекст и использовать функции для различных объектов, полезными решениями являются такие методы, как call()
, apply()
и bind()
. Рассмотрим эти методы и способы их использования.
Значения this
В JavaScript ключевое слово this
представляет собой контекст выполнения функции. Однако его значение меняется в зависимости от того, как и где вызывается функция. Вот несколько базовых понятий.
- Глобальный контекст: когда функция вызывается в глобальном контексте (например, в окне браузера),
this
представляет глобальный объект (window
).
console.log(this === window); // true
- Контекст функции: когда функция вызывается как метод объекта,
this
представляет этот объект.
const obj = {
name: "Object",
logName() {
console.log(this.name);
}
};
obj.logName(); // Вывод: объект
- Обработчики событий: внутри обработчика события
this
представляет элемент, вызвавший событие.
document.querySelector("#button").addEventListener("click", function() {
console.log(this); // "this" представляет элемент #button
});
- Функции-конструкторы: внутри функции-конструктора
this
представляет собой только что созданный объект.
function Person(name) {
this.name = name;
}
const person1 = new Person("Ozan");
console.log(person1.name); // Вывод: Ozan
Эти базовые понятия обобщены, чтобы заложить основу для понимания того, как можно управлять this
с помощью таких методов, как call()
, apply()
и bind()
.
Метод call()
Базовое использование
function.call(object, arg1, arg2, ...);
- function: функция, которая будет вызвана с определенным контекстом;
- object: значение
this
внутри функции;
- arg1, arg2, …: аргументы, передаваемые функции.
Пример 1
const obj1 = {
number1: 20,
number2: 50
};
function totalNumber(num1, num2) {
console.log(this.number1 + this.number2 + num1 + num2);
}
totalNumber.call(obj1, 40, 60); // Вывод: 170
Пример 2
const user = {
name: "Reader",
greet(greeting) {
console.log(`${greeting}, ${this.name}!`);
}
};
user.greet.call(user, "Hello"); // Вывод: Hello, Reader!
const admin = {
name: "Admin"
};
user.greet.call(admin, "Hello"); // Вывод: Hello, Admin!
Пример 3
function sum(a, b) {
return this.base + a + b;
}
const context = { base: 10 };
const result = sum.call(context, 5, 7); // Вывод: 22
Пример 4
function sum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
this.result = total;
}
sum.call(null, 3, 7, 5, 2, 8);
console.log(result); // Вывод: 25
Метод apply(): передача аргументов в виде массива
Метод apply()
, как и call()
, используется для вызова функции с определенным контекстом. Отличие заключается в том, что аргументы передаются в виде массива.
Базовое использование
function.apply(object, [arg1, arg2, ...]);
Пример 1
const obj1 = {
number1: 20,
number2: 50
};
function totalNumber(num1, num2) {
console.log(this.number1 + this.number2 + num1 + num2);
}
totalNumber.apply(obj1, [40, 60]); // Вывод: 170
Пример 2
const calculator = {
addNumbers: function (num1, num2) {
console.log(`Total: ${this.result + num1 + num2}`);
},
result: 10
};
const numbersToAdd = [5, 7];
calculator.addNumbers.apply(calculator, numbersToAdd); // Вывод: всего: 22
Пример 3
const obj1 = { number: 10 };
function doubleNumber(x) {
console.log(this.number * x);
}
doubleNumber.apply(obj1, [5]); // Вывод: 50
Пример 4
const numbers = [3, 7, 5, 2, 8];
function sum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
this.result = total;
}
sum.apply(null, numbers);
console.log(result); // Вывод: 25
Метод bind(): сохранение контекста для будущего использования
Метод bind()
создает новую функцию, при вызове которой ключевое слово this
устанавливается в указанное значение.
Базовое использование
const boundFunction = function.bind(object);
boundFunction(arg1, arg2, ...);
Пример 1
const obj2 = {
number1: 60,
number2: 120
};
function totalNumber(num1, num2) {
console.log(this.number1 + this.number2 + num1 + num2);
}
const bindFunction = totalNumber.bind(obj2);
bindFunction(50, 110); // Вывод: 340
Пример 2
const obj1 = {
message: "Hello World!",
greet: function () {
console.log(this.message);
}
};
const obj2 = {
message: "Hello Universe!"
};
const greetLater = obj1.greet.bind(obj2);
greetLater(); // Вывод: Hello Universe!
const greetLater2 = obj1.greet.bind(obj1);
greetLater2(); // Вывод: Hello World!
Пример 3
const product = {
domain: "unarkhive.com",
showInfo(info, launch) {
console.log(`${this.domain} [${info}], Launch Date: ${launch}`);
}
};
const showUnarkhiveInfo = product.showInfo.bind(product, "Explore curated links across various categories, updated daily.");
showUnarkhiveInfo("Jul, 2024"); // Вывод: unarkhive.com [Explore curated links across various categories, updated daily.], Launch Date: Jul, 2024
Пример 4
function workingHours(hour, word) {
console.log(`${hour}, ${word}!`);
}
const morningGreet = workingHours.bind(null, "Opening");
const eveningGreet = workingHours.bind(null, "Closing");
morningGreet("09:00"); // Вывод: 09:00, Opening! (открытие)
eveningGreet("24:00"); // Вывод: 24:00, Closing! (закрытие)
Сравнение и общий пример
- bind(): полезно для сохранения контекста для последующего использования, особенно в таких скриптах, как обработчики событий;
- call() и apply(): используются для немедленного вызова функции с определенным контекстом;
call()
принимает аргументы по отдельности, аapply()
— в виде массива.
Пример
const obj1 = {
first: 20,
second: 50
};
const obj2 = {
first: 60,
second: 120
};
function totalNumber(arg1, arg2) {
console.log(this.first + this.second + arg1 + arg2);
}
totalNumber(40); // NaN (не число)
totalNumber.call(obj1, 40, 60); // Вывод: 170
totalNumber.apply(obj1, [40, 60]); // Вывод: 170
const bindFunction = totalNumber.bind(obj2);
bindFunction(50, 110); // Вывод: 340
Заключение
Понимание и эффективное использование методов call()
, apply()
и bind()
в JavaScript могут значительно улучшить вашу способность управлять контекстами функций. Такое понимание гарантирует, что функции будут работать ожидаемо в различных объектах и скриптах, повышая надежность и гибкость кода.
Читайте также:
- 10 ключевых функций массивов JavaScript
- Почему стоит избегать метода push при разработке на JavaScript
- Как создать планировщик по управлению недвижимостью с помощью Bryntum и ванильного JavaScript
Читайте нас в Telegram, VK и Дзен
Перевод статьи Ozan Tekin: Call, Apply, and Bind Functions in JavaScript: Practical Guide