JS Intermediate

call, apply, bind

Научиться явно задавать this для функций с помощью call, apply и bind, понимая разницу между ними.

Средний (Intermediate)

Кратко

call и apply вызывают функцию сразу с заданным this. Разница: call принимает аргументы по одному, apply — массивом. bind создаёт новую функцию с заранее заданным this (не вызывает сразу).


Подробно

Зачем нужен явный this?

Иногда нужно вызвать функцию «от имени» другого объекта:

function greet() { console.log(Привет, ${this.name}); }

const user = { name: 'Анна' }; // greet.call(user) — вызвать greet, сделав this = user

call(thisArg, ...args): greet.call(user); // 'Привет, Анна'

greet.call(user, 'дополнительные', 'аргументы');

apply(thisArg, argsArray): greet.apply(user, ['дополнительные', 'аргументы']);

Разница call vs apply:

  • call: аргументы через запятую: fn.call(obj, a, b, c)
  • apply: аргументы массивом: fn.apply(obj, [a, b, c])

bind(thisArg, ...partialArgs): const boundGreet = greet.bind(user); boundGreet(); // 'Привет, Анна' — вызов в любой момент

bind НЕ вызывает функцию — он создаёт НОВУЮ функцию с фиксированным this.

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

  • call — вызов сразу с аргументами
  • apply — вызов сразу с массивом аргументов
  • bind — создание новой функции для будущего вызова

Ментальная модель

call — как сказать «прочитай это письмо, обращаясь к этому человеку» (сразу). apply — то же, но аргументы в конверте (массиве). bind — как создать шаблон письма с заранее вписанным именем (новая функция).


Примеры

**Самый простой:**

javascript
function greet(greeting) {
  console.log(`${greeting}, ${this.name}!`);
}

const user = { name: 'Анна' };

greet.call(user, 'Привет');   // 'Привет, Анна!'
greet.apply(user, ['Здравствуй']); // 'Здравствуй, Анна!'

call и apply вызывают функцию сразу с заданным this.

**Простой:**

javascript
function multiply(a, b) {
  return a * b;
}

// call — аргументы по одному
console.log(multiply.call(null, 2, 3)); // 6

// apply — аргументы массивом
console.log(multiply.apply(null, [2, 3])); // 6

// bind — создаёт новую функцию
const double = multiply.bind(null, 2);
console.log(double(5)); // 10 (2 * 5)

bind с частичными аргументами — удобный способ создать специализированную функцию.

**Реальный пример:**

javascript
const button = document.querySelector('#myButton');

// Проблема: this теряется в callback
// button.addEventListener('click', user.handleClick);
// this = button, не user!

// Решение 1: bind
// button.addEventListener('click', user.handleClick.bind(user));

// Решение 2: arrow function (предпочтительнее)
// button.addEventListener('click', () => user.handleClick());

bind решает проблему потери this при передаче метода как callback.


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

**Неправильно:** Путать call и apply

**Почему:** call принимает аргументы по одному, apply — массивом.

**Правильно:** call(obj, a, b, c) vs apply(obj, [a, b, c]).

**Неправильно:** Думать, что bind вызывает функцию

**Почему:** bind создаёт НОВУЮ функцию. Для вызова нужен дополнительный ().

**Правильно:** bound() — вызов. bind() — только создание.

**Неправильно:** Использовать bind когда нужен arrow function

**Почему:** Arrow function проще: () => obj.method(). Не нужен bind.

**Правильно:** Для callback'ов предпочтительнее arrow functions.


Важно запомнить

  • call(thisArg, ...args) — вызов сразу
  • apply(thisArg, [args]) — вызов сразу с массивом
  • bind(thisArg) — создаёт новую функцию
  • bind с частичными аргументами — partial application
  • Для callback'ов предпочтительнее arrow functions

Связь

Назад: Вы понимаете связывание this (JI4) — теперь у вас есть инструменты для управления им.

Вперёд: Следующий урок (JI6) — рекурсия и стек вызовов.

Материалы курса JS Intermediate — PROlab Academy.