← Назад к вопросам
В чем разница между методом 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