Нет подъема в операторе catch?

У меня есть этот код:

(function() {
   var ex;
   try {
       throw new Error('blah');
   } catch(ex) {
       console.log('ex i here:', ex);
   }
   console.log('ex out here:', ex);

   return 'hi';
})()

Это журналы:

пример я здесь: Ошибка ('blah');

ex здесь: не определено

Почему это так? Я бы подумал, что из-за подъема ex будет установлен за пределами этой области блока, поэтому он должен быть доступен в ex out here.

Я ожидал, что это будет работать аналогично циклу for:

for (i=0; i<2; i++) {
}
console.log(i); // gives 2

person Noitidart    schedule 28.03.2019    source источник
comment
catch(ex) Это ex предназначено для вас.   -  person Keith    schedule 28.03.2019
comment
Возможный дубликат области действия предложения catch JavaScript   -  person Kirk Larkin    schedule 28.03.2019
comment
ex в catch - это не объявленная переменная, это параметр, который на самом деле затеняет вашу ex переменную   -  person Kaddath    schedule 28.03.2019
comment
13.15 try Заявление: Предложение catch предоставляет код обработки исключений. Когда предложение catch перехватывает исключение, его параметр CatchParameter привязывается к этому исключению.   -  person Andreas    schedule 28.03.2019
comment
Вы никогда не определяли ex, только объявляли его. Тот, что в улове, - это параметр ex, а не переменная, которую вы объявили   -  person Huangism    schedule 28.03.2019
comment
@KirkLarkin Я так не думаю ... Дело не в исключении «переменная параметра»   -  person FZs    schedule 28.03.2019
comment
@Kaddath, не могли бы вы объяснить, что значит тень. Я не понимаю этого. Я добавил пример цикла for, который влияет на hoisted.   -  person Noitidart    schedule 28.03.2019
comment
Спасибо @FZs - я тоже думаю, что это другое, я в заявлении catch, в отличие от этой темы.   -  person Noitidart    schedule 28.03.2019
comment
Затенение @Noitidart означает, что параметры являются переменной, отличной от той, которая находится во внешней области. Несмотря на то, что у них одинаковое имя, параметр отличается, и у вас больше нет доступа к переменной с тем же именем из внешней области. В вашем примере две переменные с именем ex — это две разные переменные: одна во внешней области видимости, а другая — параметр.   -  person Mark    schedule 28.03.2019


Ответы (3)


Вы путаете несколько вещей.

Переменные, определенные как var, имеют область действия. Параметр в catch не поднимается, он имеет блочную область видимости (только в той части catch).

Как вы можете видеть в этом примере: ab поднимается, а затем доступен снаружи захватной части. ex2 не существует вне контекста.

(function() {
   var ex;
   try {
       throw new Error('blah');
   } catch(ex2) {
       var ab = 3;
       console.log('ex is here:', ex2.message);
   }
   console.log(ab);
   console.log(ex2);
   console.log('ex out here:', ex);

   return 'hi';
})()

В вашем примере создается другая переменная с тем же именем, но с другой областью действия. Если это происходит, то (почти во всех языках) используется «самая глубокая» переменная в вашем контексте. Если вы хотите вывести ошибку за пределы catch с помощью hositeing, вы можете:

(function() {
   try {
       throw new Error('blah');
   } catch(ex2) {
       var ex = ex2;
       console.log('ex is here:', ex2.message);           
   }
   console.log(ex.message);

   return 'hi';
})()

person libik    schedule 28.03.2019
comment
Это потрясающе, спасибо. Я пытался получить переменную, доступную вне области видимости. И был смущен, почему не происходит подъема. - person Noitidart; 28.03.2019

Этот код ведет себя так

  (function() {
   var ex1;
   try {
       throw new Error('blah');
   } catch(ex2) {
       console.log('ex i here:', ex2);
   }
   console.log('ex out here:', ex1);

   return 'hi';
  })()

Это связано с тем, что второй ex, объявленный в catch, виден только в области catch, для получения дополнительной информации посетить


Что касается цикла, в этих итерациях js ищет объявление переменной «i» ближайшей области, которая его содержит, которая в данном случае является родителем, поэтому изменяемая переменная «i» — это переменная, объявленная в начале как внутри цикла de нет объявления переменной.

person Tabare    schedule 28.03.2019

Из try ... catchутверждения:

Когда в блоке try генерируется исключение, exception_var (например, e в catch (e)) содержит значение, указанное оператором throw. Вы можете использовать этот идентификатор для получения информации о выброшенном исключении. Этот идентификатор является локальным для предложения catch. То есть он создается при вводе предложения catch, а после завершения выполнения предложения catch идентификатор больше недоступен.

person Nina Scholz    schedule 28.03.2019