// Что будет выведено в консоли и почему? const side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side, }; console.log(square.area()); // ? console.log(square.perimeter()); // ? const area = square.area; console.log(area()); // ? const area2 = square.area.bind({ side: 4 }).bind({ side: 7 }); console.log(area2()); // ?
Ответ
// Что будет выведено в консоли и почему? const side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side, }; console.log(square.area()); // 25 console.log(square.perimeter()); // NaN const area = square.area; console.log(area()); // NaN const area2 = square.area.bind({ side: 4 }).bind({ side: 7 }); console.log(area2()); // 16
🎯 Зачем спрашивают
- Проверить понимание механизма контекста (
this) в JavaScript и способность объяснить его на уровне исполнения кода.
- Убедиться, что кандидат различает типы функций и осознаёт их влияние на контекст:
function(создаёт свойthisпри вызове);arrow function(замыкаетthisиз внешней области).
- Проверить знание типичных ловушек: потеря контекста при деструктуризации или передаче метода как callback.
- Понять, насколько глубоко кандидат понимает работу
bind,call,applyи их отличия.
📝 Ответ
Прежде, чем бросаться решать задачу, внимательно прочитайте весь код. Часто в подобных задачах кандидаты косячат из-за невнимательности.
Цель данной задачи проверить понимание работы контекста (this) и его особенностей.
При чтении кода обращайте внимание на:
- тип используемых переменных (var, let, const)
- если используется var, есть ли “use strict” режим
- тип функции (arrow, function declaration)
Пойдем по порядку.
const side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side, }; // #1 console.log(square.area()); // 25 // #2 console.log(square.perimeter()); // NaN
В первом случае вызывается метод у объекта, объявленный через сокращённый синтаксис объекта (аналог function expression). Поэтому
this будет ссылать на объект до точки. А значит, this.side будет равен 5.
5*5 = 25.Во втором случае будет вызван метод объекта, объявленный как стрелочная функция. Стрелочные функции не имеют своего контекста,
this будет ссылать на внешний контекст. В данном случае — это контекст всего скрипта, то есть window. В window нет переменной с идентификатором side, поэтому this.side будет равен undefined.
Любая математическая операция, где хотя бы один операнд не является числом, будет выдавать NaN (not a number).this определяется способом вызова функции, а не местом объявления.const side = 20; const square = { side: 5, area() { return this.side * this.side; }, perimeter: () => 4 * this.side, }; // #3 const area = square.area; console.log(area()); // NaN // #4 const area2 = square.area.bind({ side: 4 }).bind({ side: 7 }); console.log(area2()); // 16
В третьем случае идет присвоение метода в переменную. Это ведет к потере контекста. Из-за чего
this будет ссылать на window. Потеря контекста происходит, потому что при присвоении
square.area → area теряется связь “кто вызвал функцию”.undefined * undefined даст NaN.
В четвертом случае метод функции
bind переопределяет исходный контекст. Данный метод как раз и нужен для борьбы с потерей контекста.
Важно помнить, что переопределине срабатывает единожды, повторные перепривязки не сработают. Потому что bind возвращает новую функцию, у которой контекст уже «жёстко зафиксирован».Поэтому 4 * 4 = 16.
⚖️ Компромиссы
🔎 Встречные вопросы
- Что делает
.call()и.apply()по сравнению сbind()?
- Как можно сохранить контекст без
bind()?
- Как работает
thisв классах и при наследовании?
- В чем особенность стрелочных функция?
- Что такое “use strict”? Как он работает?
🚩 Красные флаги
- Уверенное утверждение, что
thisв стрелочной функции =window.
- Попытка решить задачу без анализа, «на автомате».
- Не упоминание строгого режима.
🛠 Практика
Задача 1
"use strict"; function a () { console.log(this); } function b () { a(); } b();
Задача 2
"use strict"; function a () { console.log(this); } function b () { a(); } const c = { a, b, } c.a(); c.b();
Задача 3
"use strict"; const a = () => { console.log(this); }; const c = { a, b: () => { console.log(this); }, }; c.a(); c.b();
📚 Источники / ссылки
iliakanПривязка контекста к функции
Привязка контекста к функции
При передаче методов объекта в качестве колбэков, например для setTimeout, возникает известная проблема – потеря this.
GitHubYou-Dont-Know-JS/get-started/ch3.md at 2nd-ed · getify/You-Dont-Know-JSYou-Dont-Know-JS/get-started/ch3.md at 2nd-ed · getify/You-Dont-Know-JS
A book series (2 published editions) on the JS language. - getify/You-Dont-Know-JS