Почему const выдает ошибку при нескольких запусках кода внутри if () или try {} catch (e) {}? - PullRequest
3 голосов
/ 11 ноября 2010

Я пытаюсь объявить группу констант, используя const.Моя проблема в том, что при тестировании кода в консоли Firebug выдается сообщение об ошибке «redeclaration of const foo».

Я попытался обернуть его в блок try{}catch(e){}, но это не помогло, идаже при попытке обойти его, используя следующий код (опубликованный минус все «отладочные» вызовы console.info () для ясности), он все равно выдает ошибку при запуске во второй раз:

if(!chk_constsDeclaredYet) {
  var chk_constsDeclaredYet = true;
  const foo="bar";
}

Myвопрос в том, что, хотя const находится в if () {}, когда код запускается во второй раз, почему на const foo даже смотрят?

NB: коддолжен быть запущен в консоли javascript firebug , и рабочий процесс, которого я пытаюсь достичь:

  1. вставьте код в консоль firebug
  2. run run (создание констант)
  3. я делаю редактирование кода в консоли, не перезагружая страницу (константы все еще определены в контексте страницы)
  4. снова нажимаем run (используя if () {}, чтобы избежать повторного выделения строк)константы яесли они уже были объявлены предыдущим прогоном)
  5. повторить с (3)

вывод firebug:

//FIRST RUN::
>>> console.group() console.info('--code start--'); ...console.info('--code end--'); console.groupEnd()
--code start--
chk_constsDeclaredYet = undefined
foo = undefined
--if()--
--if() running..--
--end if()--
chk_constsDeclaredYet = true
foo = bar
--code end--

//SECOND RUN::
>>> console.group() console.info('--code start--'); ...console.info('--code end--'); console.groupEnd()
TypeError: redeclaration of const foo { message="redeclaration of const foo", more...}

Ответы [ 3 ]

4 голосов
/ 11 ноября 2010

Это старый ответ. Я написал немного более новый ответ , касающийся аналогичных проблем "const re-assignment / scope", где я показываю, что возникающие ошибки, если таковые имеются, различаются в зависимости от метода выполнения и браузера.

Поскольку const (который не является частью стандарта ECMAScript 5-го издания) имеет значение различное в ECMAScript 6-м издании, я бы рекомендовал избегать его в текущем коде.


const, как и var, имеет «функциональную область». Я подозреваю, проблема возникает из-за того же вида повышения "на вершину функции" в привязке , что происходит с var (это объясняет, почему исключение не происходит из назначения но из декларации). То есть любые последующие const x = ..., везде, где они появляются , считаются недействительными, поскольку предыдущее объявление уже существует (по определению может быть только один констант данного имени на область действия ). Однако const может принимать любое значение, поэтому назначение происходит на сайте const x = ..., так же, как назначение происходит на сайте var x = ..., даже несмотря на то, что аннотация / привязка была повышена до верхнего уровня. объема.

Вот простой тестовый пример, который более четко демонстрирует проблему:

function x () { if (true) { const a = 1 } else { const a = 2 }}
// => TypeError: redeclaration of const a @ <x-jsd:interactive-session

Как видите, ошибка возникает при объявлении функции и , а не при выполнении функции. Вот почему try / catch не работает. Поведение также может зависеть от интерактивного инструмента, с которым вы имеете дело, в зависимости от того, как он выполняет код (например, это один и тот же контекст выполнения каждый раз?).

Тем не менее, это прекрасно работает и подкрепляет первоначальное предложение выше:

(function x() { if (false) { const c = 1 }; return c })()
// => undefined

С https://developer.mozilla.org/en/JavaScript/Reference/Statements/const

(выделено жирным шрифтом)

Создает константу, которая может быть глобальной или локальной для функции, в которой она объявлена. Константы соответствуют тем же правилам области видимости, что и переменные.

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

Константа не может делиться своим именем с функцией или переменной в той же области.

const является специфичным для Mozilla расширением , оно не поддерживается IE, но частично поддерживается Opera начиная с версии 9.0 и Safari.

1 голос
/ 11 ноября 2010

A const тип должен всегда равняться постоянному значению. Если оператор if может изменить значение константы, он, вероятно, должен быть var, поскольку его значение может варьироваться.

Но проблема, по-видимому, заключается в том, что вы устанавливаете значение константы дважды. Вы инициализируете константу при первом запуске кода. Поскольку константа имеет значение при повторном запуске, вы получите исключение. Если вы переместите const foo = 'bar'; в начало вашего скрипта, вы не увидите этой проблемы. Но еще раз, если вы хотите, чтобы это значение изменялось в зависимости от логики, вам понадобится var.

Редактировать

Если вы читаете сообщение об исключении, оно говорит "redeclaration of const foo". Это означает, что вы НЕ МОЖЕТЕ объявлять foo дважды. Теперь в консоли каждый раз, когда вы запускаете код (без обновления), предыдущие переменные все еще находятся в области видимости. Таким образом, теоретически вы объявляете const foo несколько раз, даже если вы видите его только один раз в своем коде. Вы не можете заключить его в блоки if / else, потому что для этого все еще требуется const foo = 'bar', что по-прежнему является недопустимым объявлением.

Возможно, вам придется согласиться на обновление страницы между запуском измененного кода.

0 голосов
/ 11 ноября 2010

Я не знаю, является ли это лучшим способом, но eval позволит вам обойти это:

if( !chk_constsDeclaredYet ){ eval("const foo = \"bar\"") }
...