Чем отличается вызов функции с call, apply и bind?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Средний
#JavaScript #Функции #База JS

Краткий ответ

call, apply и bind — это методы функций, которые позволяют управлять контекстом выполнения ([this]) и параметрами:

  • call(obj, arg1, arg2) — вызывает функцию с указанным контекстом и аргументами через запятую
  • apply(obj, [arg1, arg2]) — то же, что и call, но аргументы передаются массивом
  • bind(obj, arg1, arg2) — не вызывает функцию, а создаёт новую с фиксированным контекстом
function greet(greeting, punctuation) {
  return greeting + ', ' + this.name + punctuation;
}
 
const person = { name: 'Иван' };
 
greet.call(person, 'Привет', '!');   // 'Привет, Иван!'
greet.apply(person, ['Привет', '!']); // 'Привет, Иван!'
const boundGreet = greet.bind(person, 'Привет', '!');
boundGreet(); // 'Привет, Иван!'

Полный ответ

call, apply и bind — это методы, которые позволяют “одевать” функцию в разные “костюмы” (контексты). Представьте, что у вас есть универсальный пульт, и вы можете подключать его к разным устройствам. 🎮

Что такое call, apply, bind

Это специальные методы, которые есть у всех функций. Они позволяют управлять тем, чему будет равен [this] внутри функции.

Простые примеры

call — вызов с аргументами через запятую

function introduce(age, city) {
  return 'Меня зовут ' + this.name + ', мне ' + age + ' лет, я из ' + city;
}
 
const person = { name: 'Иван' };
 
// Вызываем функцию в контексте person
introduce.call(person, 25, 'Москвы');
// 'Меня зовут Иван, мне 25 лет, я из Москвы'

apply — вызов с аргументами в массиве

const person = { name: 'Иван' };
 
// Те же параметры, но в массиве
introduce.apply(person, [25, 'Москвы']);
// 'Меня зовут Иван, мне 25 лет, я из Москвы'

bind — создание новой функции

const person = { name: 'Иван' };
 
// Создаём новую функцию с фиксированным контекстом
const boundIntroduce = introduce.bind(person, 25, 'Москвы');
 
// Теперь можно вызывать без параметров
boundIntroduce(); // 'Меня зовут Иван, мне 25 лет, я из Москвы'

Главные отличия

call vs apply

function sum(a, b, c) {
  return this.base + a + b + c;
}
 
const obj = { base: 10 };
 
// call — аргументы через запятую
sum.call(obj, 1, 2, 3); // 16
 
// apply — аргументы в массиве
sum.apply(obj, [1, 2, 3]); // 16

bind — не вызывает функцию

function multiply(a, b) {
  return this.factor * a * b;
}
 
const obj = { factor: 10 };
 
// bind создаёт новую функцию, но не вызывает её
const boundMultiply = multiply.bind(obj, 2);
 
// Теперь boundMultiply — это новая функция
boundMultiply(3); // 60 (10 * 2 * 3)

Когда использовать что

call — когда параметры известны

// Подходит, когда вы знаете все параметры
func.call(context, arg1, arg2, arg3);

apply — когда параметры в массиве

// Удобно, когда параметры приходят в массиве
const args = [1, 2, 3];
func.apply(context, args);

bind — для создания специализированных функций

// Создаём функцию с фиксированным контекстом
const logUser = console.log.bind(console, 'Пользователь:');
 
logUser('Иван'); // 'Пользователь: Иван'

Частые ошибки

Путаница между call и apply

function calculate(a, b) {
  return this.multiplier * (a + b);
}
 
const obj = { multiplier: 10 };
 
// ❌ Неправильно — apply ждёт массив
// calculate.apply(obj, 5, 3); // Ошибка!
 
// ✅ Правильно
calculate.apply(obj, [5, 3]); // 80
 
// ✅ Или используйте call
calculate.call(obj, 5, 3); // 80

Забыть вызвать bind

function greet() {
  return 'Привет, ' + this.name;
}
 
const person = { name: 'Иван' };
 
// ❌ Забыли вызвать bind
const boundGreet = greet.bind(person); // Это функция!
// boundGreet; // Не вызовет функцию
 
// ✅ Нужно вызвать
boundGreet(); // 'Привет, Иван'

Простые правила

  1. call — вызывает функцию с контекстом и аргументами через запятую 📞
  2. apply — то же, что и call, но аргументы в массиве 📋
  3. bind — создаёт новую функцию с фиксированным контекстом 🔗
  4. call/apply — сразу вызывают функцию 🚀
  5. bind — возвращает функцию для последующего вызова 🎯

Понимание этих методов помогает гибко управлять контекстом и параметрами функций. Это очень полезно при работе с объектами и методами! 💪


Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪