this - это окружающий контекст, в котором определена стрелочная функция
Стрелочная функция не создает свой собственный контекст выполнения, а берет this из внешней функции, в которой она определена. Другими словами, стрелочная функция определяет this лексически.
В следующем примере показана прозрачность контекста:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
log() {
console.log(this === myPoint); // => true
setTimeout(() => {
console.log(this === myPoint); // => true
console.log(this.x + ':' + this.y); // => '95:165'
}, 1000);
}
}
const myPoint = new Point(95, 165);
myPoint.log();
setTimeout() вызывает стрелочную функцию с тем же контекстом (объект myPoint), что и метод log(). Как видно, стрелочная функция наследует контекст функции, в которой она определена.
Обычная функция в этом примере создаст свой собственный контекст (window или undefined). Поэтому чтобы тот же код работал правильно с выражением функции, необходимо вручную связать контекст: setTimeout(function() {...}.bind(this)). Выглядит это довольно громоздко, что делает использование стрелочной функции - более ясным и коротким решением.
Если стрелочная функция определена в самой верхней области видимости (вне любой функции), контекстом всегда является глобальный объект (window в браузере):
const getContext = () => {
console.log(this === window); // => true
return this;
};
console.log(getContext() === window); // => true
Стрелочная функция связана с лексическим this раз и навсегда. this не может быть изменено даже при использовании методов модификации контекста:
const numbers = [1, 2];
(function() {
const get = () => {
console.log(this === numbers); // => true
return this;
};
console.log(this === numbers); // => true
get(); // => [1, 2]
// Попытаемся вручную поменять контекст стрелочной функции
get.call([0]); // => [1, 2]
get.apply([0]); // => [1, 2]
get.bind([0])(); // => [1, 2]
}).call(numbers);
Независимо от того, как вызывается стрелочная функция get(), она всегда сохраняет лексический контекст numbers. Непрямой вызов с другим контекстом get.call([0]) или get.apply([0]), повторное связывание get.bind([0])() не имеют никакого эффекта.
Стрелочную функцию нельзя использовать в качестве конструктора. Вызов ее как конструктора new get() вызовет ошибку TypeError.