call() в JavaScript

call() - это метод функции, который позволяет вызвать функцию и явно указать, чему будет равен this внутри нее.

function showName() {
  console.log(this.name);
}

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

showName.call(user);

Результат:

Анна

Функция showName() вызвалась так, будто она принадлежит объекту user.

Что такое call()

Обычно значение this зависит от того, как функция была вызвана.

Если функция вызывается как метод объекта, this указывает на этот объект.

let user = {
  name: 'Игорь',
  showName: function () {
    console.log(this.name);
  }
};

user.showName();

Результат:

Игорь

Метод call() позволяет указать this вручную.

function showName() {
  console.log(this.name);
}

let admin = {
  name: 'Ольга'
};

showName.call(admin);

Результат:

Ольга

Синтаксис

Запись выглядит так:

functionName.call(thisValue, argument1, argument2);

Первый аргумент в call() - значение для this.

Все следующие аргументы передаются в саму функцию.

function greet(message) {
  console.log(message + ', ' + this.name + '!');
}

let user = {
  name: 'Мария'
};

greet.call(user, 'Привет');

Результат:

Привет, Мария!

Передача this

Главная задача call() - вызвать функцию с нужным объектом в роли this.

function showInfo() {
  console.log(this.name + ', ' + this.age);
}

let user = {
  name: 'Анна',
  age: 25
};

showInfo.call(user);

Результат:

Анна, 25

Внутри функции this.name и this.age берутся из объекта user.

Передача аргументов

После первого аргумента в call() можно передавать обычные аргументы функции.

function getFullInfo(city, job) {
  return this.name + ', ' + city + ', ' + job;
}

let user = {
  name: 'Игорь'
};

console.log(getFullInfo.call(user, 'Москва', 'Frontend developer'));

Результат:

Игорь, Москва, Frontend developer

user стал значением this, а строки ‘Москва’ и ‘Frontend developer’ попали в параметры city и job.

Один метод для разных объектов

call() удобно использовать, когда одна функция должна работать с разными объектами.

function showRole() {
  console.log(this.name + ': ' + this.role);
}

let admin = {
  name: 'Анна',
  role: 'admin'
};

let editor = {
  name: 'Игорь',
  role: 'editor'
};

showRole.call(admin);
showRole.call(editor);

Результат:

Анна: admin
Игорь: editor

Функция одна, но данные берутся из того объекта, который передали первым аргументом в call().

call() и стрелочные функции

call() не меняет this у стрелочных функций.

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

const showName = () => {
  console.log(this.name);
};

showName.call(user);

Стрелочная функция не создает свой this. Она берет его из внешней области видимости, поэтому передача user через call() не сработает как с обычной функцией.

Если нужно управлять this через call(), используйте обычную функцию.

call(), apply() и bind()

У функций есть еще похожие методы: apply() и bind().

call() вызывает функцию сразу и передает аргументы через запятую.

getFullInfo.call(user, 'Москва', 'Frontend developer');

apply() тоже вызывает функцию сразу, но аргументы передаются массивом.

getFullInfo.apply(user, ['Москва', 'Frontend developer']);

bind() не вызывает функцию сразу. Он возвращает новую функцию с привязанным this.

let showUserInfo = getFullInfo.bind(user);

Подробнее эти методы лучше разбирать отдельно, но общая идея у них одна: работа со значением this.

Итого

1. call() вызывает функцию сразу.

2. Первый аргумент call() задает значение this.

3. Остальные аргументы передаются в саму функцию.

4. call() полезен, когда одну функцию нужно вызвать для разных объектов.

5. У стрелочных функций call() не меняет this.