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

Как можно задать явно this у стрелочной функции?

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

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Как задать явно this у стрелочной функции?

Короткий ответ: никак нельзя явно задать this у стрелочной функции. Это принципиальная особенность стрелочных функций — они наследуют this из области видимости, в которой они определены, и это невозможно переопределить.

Почему стрелочные функции не имеют собственного this?

Стрелочные функции были спроектированы с целью избежать проблем с потерей контекста this. Они захватывают this из окружающего scope на момент определения.

const obj = {
  name: 'Object',
  
  // ✅ Обычная функция имеет собственный this
  regularFunc: function() {
    console.log(this.name); // 'Object'
  },
  
  // ❌ Стрелочная функция наследует this из obj
  arrowFunc: () => {
    console.log(this.name); // undefined (this = window)
  }
};

obj.regularFunc(); // Object
obj.arrowFunc(); // undefined

call(), apply(), bind() — не работают со стрелочными функциями

Эти методы просто игнорируются при использовании со стрелочными функциями:

const user = { name: 'Alice' };

const regularFunc = function() {
  console.log(this.name);
};

const arrowFunc = () => {
  console.log(this.name);
};

// ✅ call() работает с обычной функцией
regularFunc.call(user); // Alice

// ❌ call() НЕ работает со стрелочной функцией
arrowFunc.call(user); // undefined

// ❌ apply() НЕ работает
arrowFunc.apply(user); // undefined

// ❌ bind() НЕ работает
const boundArrow = arrowFunc.bind(user);
boundArrow(); // undefined

Почему они не работают? Потому что стрелочная функция игнорирует все попытки изменить this — она всегда использует this из области видимости, где была определена.

Пример с демонстрацией

// Определяем глобально
const globalArrow = () => {
  console.log(this); // window (в браузере) или global (в Node.js)
};

const obj = { name: 'Object' };

// Пытаемся изменить this
globalArrow.call(obj); // Всё равно выведет window!
globalArrow.apply(obj); // Всё равно выведет window!
globalArrow.bind(obj)(); // Всё равно выведет window!

// Стрелочная функция, определённая в методе
const myObject = {
  name: 'MyObject',
  
  method: function() {
    const arrow = () => {
      console.log(this.name); // Захватила 'MyObject' из method
    };
    
    arrow.call({ name: 'Other' }); // ❌ НЕ работает!
    // Всё равно выведет 'MyObject'
  }
};

myObject.method(); // MyObject

Как это выглядит в коде

// ❌ Неправильно: пытаться изменить this у стрелочной функции
class Button {
  constructor(text) {
    this.text = text;
  }
  
  // Это не поможет
  handleClick = () => {
    console.log(this.text);
  }
}

const btn = new Button('Click me');
const handler = btn.handleClick;
handler.call({ text: 'Other' }); // Выведет 'Click me', а не 'Other'

Если НУЖНО задать this явно — используй обычную функцию

// ✅ Если нужна гибкость с this, используй обычную функцию
class Component {
  constructor(name) {
    this.name = name;
  }
  
  regularMethod: function() {
    console.log(this.name);
  },
  
  // Или свяжи стрелочную функцию явно
  boundArrow = () => {
    console.log(this.name);
  }
}

const comp = new Component('MyComponent');
const handler1 = comp.regularMethod;
const handler2 = comp.boundArrow;

handler1.call({ name: 'Other' }); // Other (обычная функция)
handler2.call({ name: 'Other' }); // MyComponent (стрелочная захватила this)

Практический пример: Event Listeners

// ❌ Проблема: потеря this
class Form {
  constructor() {
    this.submitted = false;
  }
  
  handleSubmit: function() {
    this.submitted = true; // this === window в браузере!
  }
}

const form = new Form();
button.addEventListener('click', form.handleSubmit); // ❌ this потеряется

// ✅ Решение 1: Стрелочная функция (захватит правильный this)
class Form {
  constructor() {
    this.submitted = false;
  }
  
  handleSubmit = () => {
    this.submitted = true; // this === экземпляр Form ✓
  }
}

const form = new Form();
button.addEventListener('click', form.handleSubmit); // ✅ Работает!

// ✅ Решение 2: Явное связывание обычной функции
class Form {
  constructor() {
    this.submitted = false;
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  
  handleSubmit() {
    this.submitted = true;
  }
}

const form = new Form();
button.addEventListener('click', form.handleSubmit); // ✅ Работает!

Почему это спроектировано так?

Стрелочные функции создали для решения проблемы потери this:

// ❌ Обычная функция — часто теряет this
const user = {
  name: 'Alice',
  
  loadData: function() {
    setTimeout(function() {
      console.log(this.name); // undefined! this === window
    }, 1000);
  }
};

user.loadData(); // undefined

// ✅ Стрелочная функция — автоматически сохраняет this
const user = {
  name: 'Alice',
  
  loadData: function() {
    setTimeout(() => {
      console.log(this.name); // Alice! this захватилась из loadData
    }, 1000);
  }
};

user.loadData(); // Alice

Итог

На вопрос "Как задать явно this у стрелочной функции?":

Ответ: Это невозможно.

  • call(), apply(), bind() — не работают со стрелочными функциями
  • Стрелочная функция всегда использует this из области видимости, где была определена
  • Это сделано намеренно для удобства и чтобы избежать проблем с потерей контекста

Если нужна гибкость с this:

  • Используй обычную функцию (function declaration / expression)
  • Используй .bind() явно
  • Используй стрелочную функцию как обертку вокруг обычной
// Пример обертки
const flexibleArrow = (context) => {
  return function() {
    console.log(this.name);
  }.call(context);
};