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

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

1.8 Middle🔥 121 комментариев
#JavaScript Core

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

call vs apply: различие в передаче аргументов

call и apply — это методы для вызова функции с явно заданным контекстом (this). Главное различие в том, как передавать аргументы.

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

call передаёт аргументы через запятую:

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

const person = { name: 'John' };

// call(thisArg, arg1, arg2, arg3, ...)
const result = greet.call(person, 'Hello', '!');
console.log(result); // 'Hello, John!'

Синтаксис call:

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

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

apply передаёт аргументы в виде массива:

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

const person = { name: 'Jane' };

// apply(thisArg, [arg1, arg2, arg3, ...])
const result = greet.apply(person, ['Hello', '!']);
console.log(result); // 'Hello, Jane!'

Синтаксис apply:

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

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

const calculator = {
  multiply: function(a, b, c) {
    return this.factor * a * b * c;
  },
  factor: 10
};

const multiplier = calculator.multiply;

// call: аргументы через запятую
const result1 = multiplier.call(calculator, 2, 3, 4);
// 10 * 2 * 3 * 4 = 240
console.log(result1); // 240

// apply: аргументы в массиве
const result2 = multiplier.apply(calculator, [2, 3, 4]);
// 10 * 2 * 3 * 4 = 240
console.log(result2); // 240

// Оба вызова идентичны по результату!

Когда использовать call (аргументы известны)

Используй call когда количество и значения аргументов известны заранее:

function formatName(firstName, lastName) {
  return firstName + ' ' + lastName;
}

const user = {}; // this не используется в этой функции

// Аргументы известны
const fullName = formatName.call(user, 'John', 'Doe');
console.log(fullName); // 'John Doe'

Когда использовать apply (аргументы в массиве)

Используй apply когда аргументы приходят в виде массива:

function sum(a, b, c) {
  return a + b + c;
}

const numbers = [1, 2, 3]; // Аргументы в массиве

// apply распаковывает массив
const total = sum.apply(null, numbers);
console.log(total); // 6

Практический пример: поиск максимума

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

// Если использовать call, нужно распаковать вручную
const max1 = Math.max.call(null, 5, 6, 2, 3, 7); // Утомительно

// С apply намного проще
const max2 = Math.max.apply(null, numbers); // 7

// Или с spread оператором (современный подход)
const max3 = Math.max(...numbers); // 7

Практический пример: копирование массива

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];

// push.apply распакует массив
array1.push.apply(array1, array2);
console.log(array1); // [1, 2, 3, 4, 5, 6]

// Или с spread (современнее)
array1.push(...array2);

Контекст (this) в обоих методах

const user = {
  name: 'Alice',
  greet: function(greeting) {
    console.log(greeting + ', ' + this.name);
  }
};

const person = { name: 'Bob' };

// call с контекстом person
user.greet.call(person, 'Hi'); // 'Hi, Bob'

// apply с контекстом person
user.greet.apply(person, ['Hi']); // 'Hi, Bob'

// Обычный вызов
user.greet('Hi'); // 'Hi, Alice' (this === user)

Множественные аргументы

function combine(separator, a, b, c) {
  return a + separator + b + separator + c;
}

// call
const result1 = combine.call(null, '-', 'red', 'green', 'blue');
console.log(result1); // 'red-green-blue'

// apply
const args = ['-', 'red', 'green', 'blue'];
const result2 = combine.apply(null, args);
console.log(result2); // 'red-green-blue'

Разница в очитаемости

// call - более очитаемо, когда аргументы явные
greet.call(user, 'Hello', 'Mr.', 'Smith');

// apply - более очитаемо, когда аргументы динамические
const userArguments = ['Hello', 'Mr.', 'Smith'];
greet.apply(user, userArguments);

Третий метод: bind (создаёт новую функцию)

bind не вызывает функцию сразу, а возвращает новую функцию с заданным контекстом:

function greet(greeting) {
  return greeting + ', ' + this.name;
}

const user = { name: 'Charlie' };

// bind создаёт новую функцию
const boundGreet = greet.bind(user, 'Hi');
const result = boundGreet(); // Вызов без аргументов
console.log(result); // 'Hi, Charlie'

// Сравнение
greet.call(user, 'Hi'); // Вызывает сразу
greet.apply(user, ['Hi']); // Вызывает сразу
greet.bind(user, 'Hi'); // Возвращает функцию

Таблица сравнения call vs apply

Свойствоcallapplybind
Вызывает функциюДаДаНет
АргументыЧерез запятуюВ массивеЧерез запятую
Синтаксисfn.call(this, a, b)fn.apply(this, [a, b])fn.bind(this, a, b)()
КонтекстУстанавливаетсяУстанавливаетсяУстанавливается
СовременностьOKOKПредпочтительно

Практический реальный пример

class Logger {
  log(level, message) {
    console.log(`[${level}] ${message}`);
  }
}

const debugLog = new Logger();

// apply удобен с динамическими аргументами
function executeWithLogging(args) {
  debugLog.log.apply(debugLog, args);
}

executeWithLogging(['ERROR', 'Something went wrong']);
// [ERROR] Something went wrong

// call для явных аргументов
debugLog.log.call(debugLog, 'INFO', 'Operation completed');
// [INFO] Operation completed

Современная альтернатива: spread оператор

В современном JavaScript предпочитается spread оператор (...) вместо apply:

// Старый способ с apply
Math.max.apply(null, [1, 2, 3]); // 3

// Современный способ со spread
Math.max(...[1, 2, 3]); // 3

// С bind и spread
const boundMax = Math.max.bind(null);
boundMax(...[1, 2, 3]); // 3

Итоговый ответ

Главное различие: способ передачи аргументов

  • call: аргументы через запятую func.call(this, arg1, arg2)
  • apply: аргументы в массиве func.apply(this, [arg1, arg2])

Оба устанавливают контекст (this) и немедленно вызывают функцию.

Современный подход: используй spread оператор (...) вместо apply, и bind для сохранения контекста.

В чем разница между передачей аргументов в call и в apply? | PrepBro