Проанализируйте этот JavaScript-фрагмент и объясните его выводы, учитывая hoisting и область видимости: function foo(){ console.log(x); var x = 5; }\nfoo();; какие тонкие ошибки семантики здесь проявляются и как их избежать

10 Окт в 13:31
4 +1
0
Ответы
1

Код
function foo{
console.logxxx;
var x = 5;
}
foo;
выведет
undefined

Почему — шаг за шагом hoistingиобластьвидимостиhoisting и область видимостиhoistingиобластьвидимости:

При разборе функции объявления переменных var "поднимаются" hoistedhoistedhoisted к началу функции. Важно: поднимается только объявление, не присваивание.Фактически движок видит функцию как будто вы написали:
function foo{
var x; // объявление поднято вверх
console.logxxx; // x существует, но ещё не инициализирован — значение undefined
x = 5; // присваивание остаётся на месте
}Поэтому при вызове foo console.logxxx видит локальную переменную x со значением undefined, а не внешнюю переменную или ошибку.

Тонкие семантические ошибки и опасности

Ожидание ReferenceError: начинающие часто думают, что обращение до объявления должно бросить ошибку. С var это не так — возвращается undefined, что может маскировать ошибку логики.Shadowing затенениезатенениезатенение: локальный var x скрывает внешнюю x. Если вы надеялись читать внешнюю переменную — получите undefined.Неправильное использование function expressions: если вы используете var f = function{}, то объявление f поднимется, но присваивание — нет. Вызов f до присваивания приведёт к TypeError f—undefinedf — undefinedfundefined.Accidental globals: если забыть var/let/const и написать x = 5, в не‑строгом режиме создаётся глобальная переменная опасноопасноопасно.Параметры функции и var: redeclare var с именем параметра не даёт эффекта — можно запутаться.Отличие от let/const: let/const имеют TDZ temporaldeadzonetemporal dead zonetemporaldeadzone — обращение до объявления выбросит ReferenceError, что иногда полезнее для обнаружения ошибок.

Как избежать проблем рекомендациирекомендациирекомендации

Используйте let и const вместо var — они блок‑ scoped и позволяют поймать обращения до объявления ReferenceErrorReferenceErrorReferenceError.Инициализируйте переменные при объявлении, когда возможно.Объявляйте переменные в начале блока/функции или — ещё лучше — по месту использования, чтобы код был читаем.Включайте "use strict"; — это предотвратит появление неявных глобальных переменных.Используйте линтер ESLintESLintESLint с правилами, запрещающими var и запрещающими использование переменных до объявления.Предпочитайте function declarations для обычных функций ониполностьюhoistedони полностью hoistedониполностьюhoisted, а для выражений осознавайте, что это поведение отличается.

Короткие примеры для сравнения

С var вашпримерваш примервашпример => undefinedС let:
function foo{ console.logxxx; let x = 5; } // ReferenceError: Cannot access 'x' before initializationFunction declaration hoisted полностью:
foo; function foo{ console.log′ok′'ok'ok; } // OK, вывод 'ok'Function expression:
f; var f = function{console.log′hi′'hi'hi}; // TypeError: f is not a function f==undefinedf == undefinedf==undefined

Итого: в вашем примере var x объявлен hoistedhoistedhoisted до console.log, поэтому вывод — undefined. Чтобы избежать подобных неожиданностей, переходите на let/const, инициализируйте при объявлении и применяйте линтер/strict mode.

10 Окт в 14:08
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир