Подтвердить что ты не робот

Почему повторное объявление аргумента внутри try/catch бросает ReferenceError?

Я ошибочно написал повторное объявление аргумента как const в функции и вместо того, чтобы бросать SyntaxError: Identifier 'bar' has already been declared, я закончил с ReferenceError: bar is not defined..

Что вызывает такое поведение? Это была не ожидаемая ошибка, и я оставил меня в замешательстве в течение нескольких минут.

Пример кода:

function foo(bar) {
  try {
      console.log(bar);
      const bar = 123;
  } catch(err) { console.log(err) }
}
foo(456);

Если я не завершу объявление в try/catch, я получу (что я считаю) ожидаемой ошибкой.

4b9b3361

Ответ 1

Константы являются блочными, как и переменные, определенные с помощью оператора let.

Из эта статья MDN.

Поскольку вы завернули bar внутри блока фигурных скобок, его определение относится к этому блоку. И поскольку у вас есть другое объявление bar внутри этого блока, несмотря на то, что после вызова к нему компилятор попытается использовать этот новый bar вместо параметра переданного. Переименуйте их как отдельные параметры для уменьшения путаницы, поскольку можно предположить, что они содержат разные данные из-за вашего объявления.

Ответ 2

Так как объявления const являются блочными областями, объявление const bar получает начало к началу блока. (Только после try {)

Это означает, что bar на самом деле не определяется при попытке зарегистрировать его, поскольку подъем поднимает/скрывает параметр bar.

Ответ 3

Это миф о том, что const и let вообще не поднимаются. Они наполовину.:-) То есть: внутри блока, если const bar или let bar (или class bar { }, если на то пошло) появляется где угодно в этом блоке, тогда bar не может использоваться до этого объявления в блоке — даже если он существует в области сложения. Эта область между началом блока и объявлением называется временной зоной:

function foo(bar) {
  // `bar` is fine here
  try {
      // Temporal Dead Zone, `bar` cannot be used here
      console.log(bar);
      // End of TDZ
      const bar = 123;
      // `bar` would be fine here
  } catch(err) { console.log(err) }
}
foo(456);    

Ответ 4

Взято отсюда https://tylermcginnis.com/videos/var-let-const/

var - это область действия, и если вы пытаетесь использовать переменную, объявленную с помощью var перед фактическим объявлением, вы просто получите undefined. Const и пусть блокируются в скобках, и если вы пытаетесь использовать const или let переменная перед объявлением вы получите опорную ошибку.