← Назад к вопросам

В чем разница между методом call и методом apply?

1.0 Junior🔥 191 комментариев
#Node.js и JavaScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

В чем разница между методом call и методом apply

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

Оба метода позволяют вызвать функцию с указанным контекстом this. Главное отличие: call принимает аргументы отдельно, apply принимает массив аргументов. Оба работают одинаково, просто синтаксис разный.

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

function greet(greeting, punctuation) {
  console.log(greeting + ', ' + this.name + punctuation);
}

const person = { name: 'John' };

// call: функция, контекст, аргумент 1, аргумент 2, ...
greet.call(person, 'Hello', '!');
// Output: Hello, John!

greet.call(person, 'Hi', '?');
// Output: Hi, John?

Синтаксис call:

function.call(thisArg, arg1, arg2, arg3, ...)

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

function greet(greeting, punctuation) {
  console.log(greeting + ', ' + this.name + punctuation);
}

const person = { name: 'John' };

// apply: функция, контекст, массив аргументов
greet.apply(person, ['Hello', '!']);
// Output: Hello, John!

const args = ['Hi', '?'];
greet.apply(person, args);
// Output: Hi, John?

Синтаксис apply:

function.apply(thisArg, [arg1, arg2, arg3, ...])

Наглядное сравнение

const calculator = {
  base: 10,
  add: function(a, b) {
    return this.base + a + b;
  }
};

const result1 = calculator.add.call(calculator, 5, 3);
// call(object, arg1, arg2)
// result1 = 18

const result2 = calculator.add.apply(calculator, [5, 3]);
// apply(object, [arg1, arg2])
// result2 = 18

// Результат одинаковый, синтаксис разный!

Контекст this

const user1 = { name: 'Alice' };
const user2 = { name: 'Bob' };

function introduce(age, city) {
  console.log(`${this.name} is ${age} and lives in ${city}`);
}

// call — используем user1 как this
introduce.call(user1, 25, 'New York');
// Output: Alice is 25 and lives in New York

// apply — используем user2 как this
introduce.apply(user2, [30, 'London']);
// Output: Bob is 30 and lives in London

Практические примеры

1. Заимствование методов

const array1 = [1, 2, 3];
const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };

// Используем метод Array на массивоподобном объекте
const result = Array.prototype.slice.call(arrayLike);
// result = ['a', 'b', 'c']

// Или с apply
const result2 = Array.prototype.slice.apply(arrayLike);
// result2 = ['a', 'b', 'c']

2. Преобразование arguments в массив

function sum() {
  // arguments — не настоящий массив
  // Используем call/apply для преобразования
  const args = Array.prototype.slice.call(arguments);
  return args.reduce((a, b) => a + b, 0);
}

sum(1, 2, 3, 4, 5); // 15

3. Наследование и конструкторы

function Animal(name) {
  this.name = name;
}

function Dog(name, breed) {
  // call используется для наследования
  Animal.call(this, name);
  this.breed = breed;
}

const dog = new Dog('Buddy', 'Golden Retriever');
console.log(dog.name); // Buddy
console.log(dog.breed); // Golden Retriever

4. Применение функции к максимальному числу

const numbers = [5, 6, 2, 3, 7];

// Использование apply с Math.max
const max = Math.max.apply(null, numbers);
// или с spread operator
const max2 = Math.max(...numbers);

console.log(max); // 7

5. Логирование с контекстом

const logger = {
  prefix: '[LOG]',
  log: function(message) {
    console.log(this.prefix + ' ' + message);
  }
};

const errorLogger = {
  prefix: '[ERROR]',
  log: logger.log
};

logger.log('This is info');
// Output: [LOG] This is info

errorLogger.log('This is error');
// Output: [ERROR] This is error

// Без call/apply errorLogger.prefix не был бы использован
logger.log.call(errorLogger, 'System failure');
// Output: [ERROR] System failure

6. Декоратор с call

function memoize(fn) {
  const cache = {};
  
  return function(...args) {
    const key = JSON.stringify(args);
    if (key in cache) {
      return cache[key];
    }
    const result = fn.call(this, ...args);
    cache[key] = result;
    return result;
  };
}

const expensive = memoize(function(n) {
  console.log('Computing...');
  return n * n;
});

expensive(5); // Computing... → 25
expensive(5); // 25 (из кэша)

call vs apply vs bind

function sayHello(greeting, name) {
  console.log(`${greeting}, ${name}!`);
}

const person = { name: 'John' };

// call — вызывает функцию сразу
sayHello.call(person, 'Hello', 'John'); // Вызвал сразу

// apply — вызывает функцию сразу с массивом
sayHello.apply(person, ['Hi', 'John']); // Вызвал сразу

// bind — возвращает новую функцию, не вызывает
const boundGreet = sayHello.bind(person, 'Hey');
boundGreet('John'); // Вызвал потом

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

call:

  • Когда аргументы известны и можно передать их отдельно
  • Заимствование методов у других объектов
  • Паттерны наследования

apply:

  • Когда аргументы в виде массива/списка
  • Работа с динамическим числом аргументов
  • Применение функции к элементам массива

bind:

  • Создание функции с привязанным контекстом
  • Передача в качестве callback функции
  • Асинхронные операции

Современная альтернатива — spread operator

// Вместо apply
Math.max.apply(null, [5, 3, 7]); // Старый способ
Math.max(...[5, 3, 7]); // Новый способ — 7

// Вместо call
Array.prototype.slice.call(arguments);
Array.from(arguments); // Или просто используй Array.from()

Вывод

  • call и apply делают одно и то же — вызывают функцию с указанным контекстом
  • Разница только в синтаксисе передачи аргументов
  • call — для отдельных аргументов, apply — для массива
  • Современный код чаще использует bind и spread operator
  • Знать all three важно для глубокого понимания JavaScript