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

Зачем изменять контекст исполнения функции через apply?

2.0 Middle🔥 281 комментариев
#JavaScript Core

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

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

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

Зачем изменять контекст исполнения функции через apply?

Метод apply - это один из способов управления контекстом исполнения функции (значением this). Это мощный инструмент для написания гибкого и переиспользуемого кода в JavaScript.

Что такое контекст исполнения (this)?

Контекст исполнения (this) - это объект, на который ссылается функция во время выполнения. По умолчанию this указывает на глобальный объект (window в браузере) или undefined в strict mode.

const person = {
  name: "John",
  greet: function() {
    console.log("Hello, " + this.name);
  }
};

person.greet(); // "Hello, John" - this = person

const greetFunc = person.greet;
greetFunc(); // "Hello, undefined" - this = window или undefined

Методы управления контекстом

в JavaScript есть три способа изменить контекст:

1. apply - передача аргументов массивом

apply вызывает функцию с указанным контекстом и аргументами, переданными массивом.

function introduce(greeting, country) {
  return `${greeting}, I am ${this.name} from ${country}`;
}

const person = { name: "Alice" };

// apply принимает массив аргументов
const result = introduce.apply(person, ["Hello", "USA"]);
console.log(result); // "Hello, I am Alice from USA"

2. call - передача аргументов отдельными параметрами

call работает как apply, но аргументы передаются через запятую:

const result = introduce.call(person, "Hi", "Canada");
console.log(result); // "Hi, I am Alice from Canada"

3. bind - создание новой функции с привязанным контекстом

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

const boundGreet = introduce.bind(person);
const result = boundGreet("Hey", "UK");
console.log(result); // "Hey, I am Alice from UK"

Практические примеры использования apply

Пример 1: Заимствование методов другого объекта

const user1 = { name: "John", age: 25 };
const user2 = { name: "Jane", age: 30 };

function isAdult() {
  return this.age >= 18;
}

// Проверяем user2 контекстом
console.log(isAdult.apply(user2)); // true
console.log(isAdult.apply(user1)); // true

Пример 2: Объединение массивов

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

// Используем apply с методом push
Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]

// В современном JS используем spread оператор
arr1.push(...arr2);

Пример 3: Нахождение минимума/максимума

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

// Используем apply для передачи массива как аргументов
const max = Math.max.apply(null, numbers);
const min = Math.min.apply(null, numbers);

console.log(max); // 9
console.log(min); // 1

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

Пример 4: Реализация функции с переменным количеством аргументов

function sum() {
  return Array.prototype.reduce.apply(arguments, [
    (a, b) => a + b,
    0
  ]);
}

console.log(sum(1, 2, 3, 4)); // 10

Когда нужен apply?

Основные сценарии:

  1. Отсутствие прямого доступа к аргументам: когда аргументы собраны в массиве
  2. Наследование в конструкторах: вызов родительского конструктора
  3. Декораторы и обертки: когда нужно сохранить контекст
  4. Работа с методами встроенных объектов: Math.max, Array.push и т.д.
// Наследование через apply
function Animal(name) {
  this.name = name;
}

function Dog(name, breed) {
  Animal.apply(this, [name]); // Вызываем родительский конструктор
  this.breed = breed;
}

const dog = new Dog("Buddy", "Labrador");
console.log(dog.name); // "Buddy"
console.log(dog.breed); // "Labrador"

apply vs call vs bind

МетодСинтаксисАргументыСразу выполняется?
applyfunc.apply(context, [args])МассивДа
callfunc.call(context, arg1, arg2)СписокДа
bindfunc.bind(context, arg1, arg2)Список или потомНет

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

В современном JavaScript часто используют spread оператор вместо apply:

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

// Новый способ
Math.max(...[1, 2, 3, 4, 5]);

// Или arrow functions
const greet = (greeting, name) => `${greeting}, ${name}`;
const newGreet = (greeting) => greet.call(null, greeting, "World");

Вывод

apply остается полезным методом для:

  • Управления контекстом функции
  • Передачи аргументов из массива
  • Заимствования методов других объектов
  • Реализации паттернов наследования

Хотя в современном JavaScript есть более удобные альтернативы (spread, arrow functions), понимание apply критично для работы с legacy кодом и глубокого понимания JavaScript.

Зачем изменять контекст исполнения функции через apply? | PrepBro