Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
apply(): Способы передачи аргументов
apply() — это метод функции в JavaScript, который вызывает функцию с явно указанным контекстом (this) и аргументами в виде массива или array-like объекта.
Синтаксис
function.apply(thisArg, [argsArray])
Параметры:
thisArg— значение, которое будет использовано какthisпри вызове функцииargsArray— массив (или array-like объект) с аргументами для функции
Как apply принимает аргументы
1. Массив как второй параметр
function greet(greeting, punctuation) {
return greeting + ' ' + this.name + punctuation;
}
const person = { name: 'John' };
// apply принимает массив аргументов
const result = greet.apply(person, ['Hello', '!']);
console.log(result); // "Hello John!"
// Эквивалентно:
greet.call(person, 'Hello', '!');
2. Array-like объект
const arrayLike = {
0: 'Hello',
1: '!',
length: 2
};
const result = greet.apply(person, arrayLike);
console.log(result); // "Hello John!"
3. null или undefined как первый параметр
function sum(a, b) {
console.log(this); // Window (в браузере) или undefined (в строгом режиме)
return a + b;
}
const result = sum.apply(null, [5, 3]);
console.log(result); // 8
4. arguments объект (старый подход)
function wrapper() {
console.log(arguments); // Arguments { 0: 1, 1: 2, 2: 3 }
// apply принимает arguments как массив
// arguments — это array-like, а не настоящий массив
Math.max.apply(null, arguments); // Ищет максимум
}
wrapper(1, 2, 3);
Примеры использования
Пример 1: Поиск максимума/минимума
const numbers = [5, 6, 2, 3, 7];
// Math.max / Math.min не принимают массив
// Math.max(numbers) вернёт NaN
// apply распаковывает массив в отдельные аргументы
const max = Math.max.apply(null, numbers);
const min = Math.min.apply(null, numbers);
console.log(max); // 7
console.log(min); // 2
// Современный способ (ES6+):
const max2 = Math.max(...numbers); // Spread operator
const min2 = Math.min(...numbers);
Пример 2: Вызов конструктора с массивом аргументов
function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
const args = ['John', 'Doe', 30];
// apply не работает с конструкторами!
// const person = Person.apply({}, args); // Неправильно
// Нужно использовать new или new.target
const person = new (Function.prototype.bind.apply(Person, [null, ...args]))();
// Или проще в ES6:
const person2 = new Person(...args);
Пример 3: Заимствование методов у других объектов
const arrayLike = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// apply позволяет использовать методы Array на array-like объектах
const result = Array.prototype.slice.apply(arrayLike);
console.log(result); // ['a', 'b', 'c']
// Эквивалентно:
const result2 = Array.from(arrayLike);
const result3 = [...arrayLike]; // Не работает, т.к. не итерируемый
Пример 4: Логирование с переменным числом аргументов
const logger = {
log: function(level, ...args) {
console.log(`[${level}]`, ...args);
}
};
function callLogger() {
// apply передаёт все аргументы из массива
logger.log.apply(logger, ['INFO', 'User logged in', { userId: 123 }]);
}
callLogger();
// Вывод: [INFO] User logged in { userId: 123 }
Сравнение: apply, call, bind
function introduce(greeting, punctuation) {
return `${greeting}, I'm ${this.name}${punctuation}`;
}
const person = { name: 'Alice' };
// call — аргументы через запятую
const result1 = introduce.call(person, 'Hi', '!');
console.log(result1); // Hi, I'm Alice!
// apply — аргументы в массиве
const result2 = introduce.apply(person, ['Hi', '!']);
console.log(result2); // Hi, I'm Alice!
// bind — возвращает новую функцию
const boundFunc = introduce.bind(person, 'Hi', '!');
const result3 = boundFunc();
console.log(result3); // Hi, I'm Alice!
Частые ошибки при работе с apply
Ошибка 1: Забыли передать массив
// Плохо
const result = Math.max.apply(null, 5, 3, 2); // Второй параметр должен быть массивом!
// Это не будет работать как ожидается
// Правильно
const result = Math.max.apply(null, [5, 3, 2]);
Ошибка 2: Передали не array-like объект
const obj = { a: 1, b: 2 }; // Обычный объект, не array-like
// Плохо
Array.prototype.slice.apply(obj); // Вернёт пустой массив
// Нужен length
const arrayLike = { 0: 'a', 1: 'b', length: 2 };
Array.prototype.slice.apply(arrayLike); // ['a', 'b']
Ошибка 3: Забыли про контекст (this)
const obj = {
name: 'Object',
greet: function() {
console.log('Hello, ' + this.name);
}
};
// Плохо — this будет undefined или window
obj.greet.apply(null, []);
// Правильно
obj.greet.apply(obj, []);
// Или
obj.greet();
Производительность
const numbers = Array.from({ length: 100000 }, (_, i) => i);
// Способ 1: apply (старый)
console.time('apply');
Math.max.apply(null, numbers);
console.timeEnd('apply'); // ~5ms
// Способ 2: spread (новый)
console.time('spread');
Math.max(...numbers);
console.timeEnd('spread'); // ~5ms
Оба способа примерно одинаковые по производительности в современных браузерах.
Реальные примеры использования
Пример 1: Утилита для запуска функции с контекстом
function executeWithContext(
func: Function,
context: any,
args: any[] = []
) {
return func.apply(context, args);
}
const user = { name: 'Bob' };
const greet = (greeting: string) => `${greeting}, ${this.name}`;
const result = executeWithContext(greet, user, ['Hello']);
console.log(result); // Hello, Bob
Пример 2: Наследование в ES5
function Animal(name) {
this.name = name;
}
function Dog(name, breed) {
Animal.apply(this, [name]); // Вызываем родительский конструктор
this.breed = breed;
}
const dog = new Dog('Max', 'Labrador');
console.log(dog); // { name: 'Max', breed: 'Labrador' }
Пример 3: Декоратор с apply
function withLogging(fn: Function, context: any) {
return function(...args: any[]) {
console.log(`Calling ${fn.name} with args:`, args);
return fn.apply(context, args);
};
}
const add = (a: number, b: number) => a + b;
const loggedAdd = withLogging(add, null);
loggedAdd(5, 3); // Calling add with args: [5, 3] -> 8
Современные альтернативы
В ES6+ часто используется spread operator вместо apply:
// Старый способ
Math.max.apply(null, numbers);
// Новый способ
Math.max(...numbers);
// call
func.call(obj, a, b);
// можно заменить
func.apply(obj, [a, b]);
// или
func.bind(obj, a, b)();
Заключение
apply() принимает аргументы следующим образом:
- Первый параметр — контекст (this)
- Второй параметр — массив или array-like объект с аргументами
- Аргументы распаковываются — apply превращает массив в отдельные параметры
apply() полезен для:
- Вызова функций с переменным числом аргументов
- Заимствования методов
- Установки контекста (this)
- Работы с array-like объектами
В современном JavaScript часто используется spread operator (...) как альтернатива apply, так как это более удобно и читаемо.