24 апреля 2023 г. (изменено: 4 мая 2023 г.)

Канал: @cherkashindev

641

​​🧮 Задача на знание this в JavaScript

Иногда на собеседованиях дают подобные каверзные задачи, в которых необходимо хорошо понимать, как работают одновременно: стрелочные функции, контекст this и замыкания. Вот одна из задач, которую мне давали на собеседовании пару лет назад.

Что будет выведено в консоль?

function foo() {
  const x = 10;
 
  return {
    x: 20,
    bar: () => console.log(this.x),
    baz() {
      console.log(this.x);
    },
  };
}
 
foo.x = 50;
 
const obj1 = foo();
obj1.bar(); // ?
obj1.baz(); // ?
 
const obj2 = foo.call({ x: 30 });
const x = obj2.bar;
x(); // ?
obj2.bar(); // ?
obj2.baz(); // ?

Необходимая теория для решения задачи

  • this - контекст вызова функции. Если метод вызывается не на объекте, то this — глобальный объект window, иначе this указывает на объект, на котором был вызван метод.
  • У стрелочной функции нет собственного this. Если внутри стрелочной функции идёт обращение к this, его значение, как и обычная переменная, берётся из внешнего лексического окружения.
  • Если метод объекта присвоить переменной, и вызвать такую переменную-функцию, то контекст потеряется и this будет ссылаться на window. Но это не работает в случае стрелочной функции, так как у неё нет собственного this, поэтому и потерять она его не может.

Разбор задачи построчно 6. bar — стрелочная функция, this берётся из лексического окружения 7. baz — обычная функция, поэтому this будет ссылаться на возвращаемый объект 15. Так как функция foo вызывается не на объекте, то this в этом случае равен глобальному объекту — window. 16. Так как стрелочная функция берёт this из лексического окружения, то this = window. В консоль будет выведен undefined, потому что на window не определено свойство x. 17. Функция baz реализована с помощью обычной функции, поэтому в данном случае this ссылается на сам объект. В консоль будет выведено 20. 19. Здесь явно указывается контекст вызова функции — объект { x: 30 } 20-21. Так как метод bar реализован с помощью стрелочной функции, то контекст в данном случае не теряется. Используется контекст из лексического окружения — { x: 30 }. В консоль будет выведено 30. 22. Вызывается тот же метод bar, логика точно такая же. В консоль будет выведено 30. 23. Явное указание контекста при вызову функции foo никак не влияет на функцию baz, так как метод вызывается на объекте, и контекстом будет являться данный объект. В консоль будет выведено 20.

**Ответ **⬇️ undefined 20 30 30 20

Теория по теме

👍 4