Apply: примеры (JAVASCRIPT)
apply(thisArg, argsArray): anyОсновы метода apply
Метод apply() является встроенным методом объектов функций в JavaScript. Он позволяет вызвать функцию с заданным значением this и аргументами, предоставленными в виде массива или массивоподобного объекта.
Использование метода актуально в случаях, когда необходимо явно установить контекст выполнения функции или когда аргументы для вызова динамически формируются в виде массива.
Синтаксис метода: function.apply(thisArg, [argsArray])
- thisArg: Значение, которое будет передано функции как контекст
this. Если значение равноnullилиundefined, контекстом станет глобальный объект (в нестрогом режиме). - argsArray: Необязательный аргумент. Массивоподобный объект, определяющий аргументы, с которыми будет вызвана функция. Если передано значение
nullилиundefined, функция вызывается без аргументов.
Возвращаемое значение: результат выполнения вызванной функции с указанным контекстом this и аргументами.
Базовые примеры использования
Пример 1: Вызов функции с указанием контекста.
function introduce(greeting) {
return `${greeting}, меня зовут ${this.name}`;
}
const person = { name: 'Анна' };
console.log(introduce.apply(person, ['Привет']));Привет, меня зовут Анна
Пример 2: Использование для передачи массива аргументов.
function sum(a, b, c) {
return a + b + c;
}
const numbers = [5, 10, 15];
console.log(sum.apply(null, numbers));30
Пример 3: Вызов без передачи аргументов (второй параметр null).
function getContext() {
return this;
}
const myObj = { id: 1 };
console.log(getContext.apply(myObj, null) === myObj);true
Похожие методы в JavaScript
В JavaScript существуют два других метода для вызова функций с указанием контекста: call() и bind().
- call(thisArg, arg1, arg2, ...): Аналогичен
apply(), но принимает аргументы для функции не в виде массива, а списком через запятую. Предпочтителен, когда количество аргументов известно заранее. - bind(thisArg, arg1, arg2, ...): Создает новую функцию, привязанную к указанному контексту и, опционально, начальным аргументам. Функция не вызывается немедленно. Используется, когда необходимо создать отложенный вызов или передать метод как callback с сохранением контекста.
Выбор между apply и call часто зависит от формы, в которой доступны аргументы для вызова: список или массив.
Аналоги в других языках программирования
Python: Используется метод __call__ или распаковка аргументов с помощью оператора *.
def introduce(greeting):
return f'{greeting}, меня зовут {self.name}'
class Person:
def __init__(self, name):
self.name = name
person = Person('Алексей')
# Использование метода как callable
print(introduce.__get__(person, Person)('Здравствуй'))
# Альтернатива с распаковкой
args = ['Здравствуй']
print(introduce(person, *args))Здравствуй, меня зовут Алексей
PHP: Существуют функции call_user_func_array и call_user_func.
function introduce($greeting) {
return $greeting . ', меня зовут ' . $this->name;
}
class Person {
public $name = 'Мария';
}
$person = new Person();
$func = [new Person(), 'introduce'];
echo call_user_func_array($func, ['Привет']);Привет, меня зовут Мария
C#: Аналогичную функциональность можно достичь с помощью делегатов и метода DynamicInvoke.
Типичные ошибки
Ошибка 1: Передача непримитивного значения как thisArg в строгом режиме.
'use strict';
function foo() {
return this;
}
console.log(foo.apply(123)); // Примитив не преобразуется в объект-обертку123
Ошибка 2: Передача аргументов, не являющихся массивоподобным объектом.
function bar(a, b) {
return a + b;
}
console.log(bar.apply(null, 'ab')); // Строка имеет индексы 0 и 1
console.log(bar.apply(null, {0: 1, 1: 2, length: 2})); // Работает
console.log(bar.apply(null, {x: 1, y: 2})); // Ошибкаab 3 // TypeError: CreateListFromArrayLike called on non-object или аналогичная
Изменения в современных версиях
С появлением стандарта ES6 (ES2015) потребность в использовании apply() для передачи массива аргументов уменьшилась. Оператор расширения (spread operator) ... позволяет достичь аналогичного результата с более лаконичным синтаксисом.
const numbers = [5, 10, 15];
function sum(a, b, c) {
return a + b + c;
}
// Старый способ с apply
console.log(sum.apply(null, numbers));
// Новый способ с оператором расширения
console.log(sum(...numbers));30 30
Несмотря на это, apply() остается частью стандарта и поддерживается во всех средах. Его использование для явной установки контекста по-прежнему актуально.
Расширенные примеры
Пример 1: Использование для вызова конструктора (устаревший способ, возможен до ES6).
function Person(name, age) {
this.name = name;
this.age = age;
}
const args = ['Игорь', 30];
const person = new (Person.bind.apply(Person, [null, ...args]))();
// Более современная альтернатива с оператором расширения:
const person2 = new Person(...args);
console.log(person2.name);Игорь
Пример 2: Нахождение максимального значения в массиве.
const numbers = [4, 12, 7, 22, 5]; const max = Math.max.apply(null, numbers); console.log(max); // В ES6: Math.max(...numbers)
22
Пример 3: Композиция функций с использованием apply.
function compose(f, g) {
return function() {
return f.call(this, g.apply(this, arguments));
};
}
function double(x) { return x * 2; }
function increment(x) { return x + 1; }
const doubleThenIncrement = compose(increment, double);
console.log(doubleThenIncrement(5));11
Пример 4: Работа с массивоподобными объектами, например, arguments.
function logArgs() {
// Преобразование arguments в массив для использования методов Array
const argsArray = Array.prototype.slice.apply(arguments);
argsArray.forEach(arg => console.log(arg));
}
logArgs('a', 'b', 'c');a b c