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

Что делает метод apply?

1.0 Junior🔥 91 комментариев
#JavaScript Core

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

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

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

Что делает метод apply?

apply() — это встроенный метод JavaScript, который вызывает функцию с явно заданным значением this и передаёт аргументы в виде массива. Это один из трёх способов управления контекстом выполнения функции (наряду с call() и bind()).

Синтаксис

function.apply(thisArg, [arg1, arg2, arg3, ...])
  • thisArg — объект, который будет использоваться как this
  • [arg1, arg2, ...] — массив аргументов, которые будут переданы функции

Ключевое отличие от call()

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

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

const person = { name: "Иван" };

// call() - аргументы через запятую
greet.call(person, "Привет", "!");
// "Привет, я Иван!"

// apply() - аргументы в массиве
greet.apply(person, ["Привет", "!"]);
// "Привет, я Иван!"

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

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

1. Нахождение максимального значения в массиве

const numbers = [5, 2, 8, 1, 9];

// Math.max обычно принимает аргументы, а не массив
console.log(Math.max(5, 2, 8, 1, 9)); // 9

// Но с apply() можно передать массив
const max = Math.max.apply(null, numbers);
console.log(max); // 9

// Современный способ со spread оператором
const max2 = Math.max(...numbers); // 9

2. Копирование методов между объектами

const user1 = {
  name: "Мария",
  sayHi: function() {
    console.log("Привет, я " + this.name);
  }
};

const user2 = { name: "Петр" };

// Вызываем метод user1 в контексте user2
user1.sayHi.apply(user2); // "Привет, я Петр"

3. Получение типа переменной (более надежный способ)

function getType(value) {
  return Object.prototype.toString.apply(value);
}

console.log(getType([])); // "[object Array]"
console.log(getType({})); // "[object Object]"
console.log(getType("text")); // "[object String]"
console.log(getType(123)); // "[object Number]"
console.log(getType(null)); // "[object Null]"

4. Объединение массивов

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// Старый способ с apply()
const merged = [];
merged.push.apply(merged, arr1);
merged.push.apply(merged, arr2);
console.log(merged); // [1, 2, 3, 4, 5, 6]

// Современный способ
const merged2 = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

5. Вызов конструктора с массивом аргументов

function User(name, age, email) {
  this.name = name;
  this.age = age;
  this.email = email;
}

const userData = ["Анна", 30, "anna@example.com"];

// Нельзя использовать apply с new, но можно так
const user = new (Function.prototype.bind.apply(User, [null, ...userData]))();

// Или проще с spread оператором
const user2 = new User(...userData);
console.log(user2); // User { name: "Анна", age: 30, email: "anna@example.com" }

6. Функция декоратор, используя apply()

function logger(fn) {
  return function(...args) {
    console.log("Вызов функции с аргументами:", args);
    return fn.apply(this, args);
  };
}

function add(a, b) {
  return a + b;
}

const loggedAdd = logger(add);
loggedAdd(5, 3); // Вызов функции с аргументами: [5, 3] -> 8

7. Практический пример в React

// Функция для логирования всех действий компонента
function withLogging(Component) {
  return function LoggedComponent(...args) {
    console.log("Компонент отрендерен с props:", args[0]);
    return Component.apply(this, args);
  };
}

apply() vs call() vs bind()

const person = { name: "Дмитрий" };

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

// call() - вызывает сразу, аргументы через запятую
greet.call(person, "Hi", "!"); // "Hi, Дмитрий!"

// apply() - вызывает сразу, аргументы в массиве
greet.apply(person, ["Hi", "!"]); // "Hi, Дмитрий!"

// bind() - возвращает новую функцию, не вызывает
const boundGreet = greet.bind(person, "Hi", "!");
boundGreet(); // "Hi, Дмитрий!"

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

  1. Когда уже есть массив аргументов — более удобно, чем распаковывать вручную
  2. Работа с функциями, принимающими переменное количество аргументов — Math.max, Math.min
  3. Функциональное программирование — декораторы, обёртки
  4. Наследование и заимствование методов — вызов методов из других объектов

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

С появлением spread оператора (...) в ES6, apply() стал менее популярен:

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

// Современно
Math.max(...[1, 2, 3]);

// Старо
fn.apply(obj, args);

// Современно (нужен контекст)
fn.call(obj, ...args);

Однако apply() всё ещё важно понимать для:

  • Чтения старого кода
  • Работы с функциональными паттернами
  • Интервью и полноты знаний JavaScript