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

Какие знаешь методы изменения This?

2.0 Middle🔥 171 комментариев
#Soft Skills и рабочие процессы

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

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

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

Методы изменения контекста this в JavaScript

В JavaScript значение this — один из самых важных и одновременно запутанных аспектов языка. Оно определяется не тем, где функция объявлена, а тем, как она вызывается. Часто нам нужно явно управлять контекстом выполнения функции, и для этого существует несколько встроенных методов.

Явное связывание контекста

Самые прямые способы изменить this — это методы функций: call(), apply() и bind(). Они доступны у любой функции, так как она является объектом.

1. Метод call()

call() вызывает функцию с заданным значением this и отдельными аргументами (списком).

function introduce(greeting, punctuation) {
    console.log(`${greeting}, я ${this.name}${punctuation}`);
}

const person = { name: 'Анна' };

// Вызываем функцию, передавая контекст и аргументы по одному
introduce.call(person, 'Привет', '!');
// Вывод: Привет, я Анна!

Ключевое: первый аргумент call() — новый контекст (this), остальные — аргументы функции.

2. Метод apply()

apply() очень похож на call(), но принимает аргументы для функции в виде массива (или массивоподобного объекта).

function introduce(greeting, punctuation) {
    console.log(`${greeting}, я ${this.name}${punctuation}`);
}

const person = { name: 'Иван' };
const args = ['Здравствуйте', '...'];

introduce.apply(person, args);
// Вывод: Здравствуйте, я Иван...

Это исторически полезно, когда аргументы динамически собираются в массив. В современном ES6 чаще используют call() с оператором spread.

3. Метод bind()

bind() не вызывает функцию сразу. Вместо этого он создает и возвращает новую функцию, которая навсегда привязана к переданному контексту this. Это называется каррированием или созданием функции с жёстко заданным контекстом.

function logThis() {
    console.log(this.id);
}

const obj = { id: 42 };
const boundLog = logThis.bind(obj); // Создаём новую функцию, привязанную к obj

boundLog(); // Вывод: 42
// Даже если вызвать boundLog в другом контексте, this останется obj
setTimeout(boundLog, 100); // Вывод: 42

bind() также позволяет частично применять аргументы (предзаполнять их):

function multiply(a, b) {
    return a * b;
}
const double = multiply.bind(null, 2); // Фиксируем первый аргумент как 2
console.log(double(5)); // Вывод: 10 (2 * 5)

Неявные и альтернативные способы влияния на this

Помимо явных методов, контекст меняется в зависимости от способа вызова:

  • Вызов как метода объекта: this — сам объект.
    obj.method(); // this внутри method — это obj
    
  • Прямой вызов функции: this — глобальный объект (window/global) или undefined в строгом режиме ('use strict').
  • Конструктор (new): this — новый создаваемый экземпляр объекта.
  • Стрелочные функции: У них нет своего this. Они захватывают this из окружающей лексической области видимости. Их нельзя перепривязать с помощью call, apply или bind.
    const obj = {
        value: 10,
        regularFunc: function() {
            console.log(this.value); // Зависит от вызова
        },
        arrowFunc: () => {
            console.log(this.value); // this — из внешнего скоупа (например, window)
        }
    };
    

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

МетодНемедленный вызов?ВозвращаетСпособ передачи аргументов
call(thisArg, ...args)ДаРезультат функцииСписок, через запятую
apply(thisArg, [argsArray])ДаРезультат функцииМассив (или массивоподобный)
bind(thisArg, ...args)НетНовую функциюСписок (для предзаполнения)

Практические сценарии применения

  • Заимствование методов: Использовать метод одного объекта для другого.
    const car = { brand: 'Toyota' };
    const display = { brand: 'BMW', show() { console.log(this.brand); } };
    display.show.call(car); // Вывод: Toyota (заимствовали метод)
    
  • Работа с псевдомассивами: Преобразование arguments или NodeList в настоящий массив.
    function oldWay() {
        const argsArray = Array.prototype.slice.call(arguments);
    }
    // Современная альтернатива: Array.from(arguments) или spread оператор
    
  • Фиксация контекста для колбэков: Классическая проблема при передаче метода в setTimeout или обработчик событий.
    class Component {
        constructor() {
            this.state = { clicked: false };
            // Без bind this будет потерян при вызове из события
            this.handleClick = this.handleClick.bind(this);
        }
        handleClick() {
            this.state.clicked = true;
        }
    }
    

Вывод: Понимание методов call, apply и bind — фундаментально для работы с JavaScript, особенно в объектно-ориентированных и асинхронных паттернах. Они дают разработчику точный контроль над контекстом выполнения, что критически важно для предсказуемого поведения кода. В современном ES6+ часто используют стрелочные функции или поля классов, чтобы избежать необходимости в .bind(), но знание этих методов остаётся обязательным для чтения legacy-E кода и глубокого понимания языка.