Почему переопределение идентификатора функции в блоке try вызывает синтаксис?
Следующие строки JavaScript
try {
function _free() {}
var _free = 1;
} finally { }
приводят к следующей ошибке:
Uncaught SyntaxError: Identifier '_free' has already been declared
Однако следующие два блока кода JavaScript не имеют значения:
Но почему?
(среда тестирования: Chromium 61.0.3126.0)
Ответы
Ответ 1
Потому что объявления функций с блочным ограничением являются новой функцией ES6 и были сделаны безопасными (т.е. вывести ошибку при столкновении имен, аналогичную let
и const
), но другие случаи (которые являются ошибками программиста независимо) должны были оставаться обратно совместимыми и молча перезаписать функцию.
Ответ 2
Чтобы расширить на ответ Бергиса, есть разница в том, как код интерпретируется в ES5 и ES6, поскольку добавлены объявления функций с блочной областью.
Input:
function test() {
try {
function _free() { }
var _free = 1;
} finally { }
}
Так как ES5 не поддерживает функции уровня блока, _free
поднял родительскую функцию:
function test() {
var _free = function _free() { }
try {
var _free = 1;
} finally { }
}
В ES6 функция объявляется на уровне блока и семантически равна объявлению let
/const
:
function test() {
try {
let _free = function _free() { }
var _free = 1;
} finally { }
}
Это вызывает ошибку, потому что var _free
пытается объявить переменную, которая уже объявлена.
Например, это также вызывает ES6:
let _free;
var _free = 1; // SyntaxError: Indentifier '_free' has already been declared
Пока это нормально:
var _free;
var _free = 1; // No SyntaxError
Установка значения уже объявленного идентификатора в порядке:
let _free;
_free = 1;
Поэтому, чтобы установить объявленный идентификатор _free
в 1, вам нужно пропустить второе объявление:
try {
function _free() { }
_free = 1;
} finally { }