function func(x = y, y = 2) {
return [x, y];
}
func(); // ReferenceError: y is not defined
func(1); // [1, 2]
Как видно из приведенного выше кода, в области параметров функции есть скрытая TDZ, которая объясняет, почему сбой кода ниже:
function func(arg) {
let arg = 1; // SyntaxError: Identifier 'arg' has already been declared
}
Поэтому параметры функции должны быть объявлены с помощью let
, но меня смущает:
function func(arg) {
var arg = 1;
console.log(arg); // 1
}
этот код отлично работает.
Почему вы можете обновлять переменные с помощью var
? Как Javascript объявляет параметры функции?
изменить:
Я точно знаю, что вы не можете использовать let to redeclare variable. Вопрос здесь заключается в том, объявлены ли параметры функции с помощью let
, поэтому:
function func(arg) {
var arg = 1;
}
выглядит следующим образом:
let arg; // arg parameter declares here
var arg = 1; // func body
и почему это может выполняться без каких-либо исключений?
Ответ 1
имеется скрытая TDZ в области параметров функции
Да, действительно. Посмотрите здесь на несколько примеров.
Как Javascript объявляет параметры функции?
Как параметры - см. здесь для пошагового объяснения. Они не совпадают с let
и не похожи на var
, они имеют свою собственную семантику. ES6, который представил инициализаторы по умолчанию, дал им те же ограничения TDZ, что и в let
, чтобы уловить больше ошибок программиста.
Почему вы можете переопределять переменные с помощью var
?
Потому что до ES5 повторное использование переменной не является условием ошибки, и это поведение необходимо сохранить, чтобы не сломать сеть. Его можно было бы ввести только для новых функций, таких как let
и const
- или списки аргументов, в которых используются инициализаторы по умолчанию, попробуйте function x(bar, bar) {}
vs function x(bar, bar=1){}
.
Ответ 2
Это необязательно связано с аргументами функции.
Это также вызовет ошибку:
function func() {
var arg = 1;
let arg = 2
console.log(arg); // 1
}
func();
Ответ 3
Причина в том, что это связано с тем, что люди в сообществе JavaScript называют "подъемом", когда вы делаете var arg = 1
, который переводится в var arg;
arg = 1;
, однако, если var уже определен как здесь из-за параметра функции, тогда компилятор пытается быть полезным и игнорирует последующие повторные объявления вместо того, чтобы бросать ошибку... что, вероятно, является неожиданным поведением и не сопровождалось новым объявлением переменной let, однако он должен оставаться там для обратной совместимости.
Ответ 4
let
добавлен совсем недавно, и с ним был введен бросок ошибки, который проявляется, когда вы пытаетесь объявить переменную, которая включает let
дважды. Этого не происходит с var
, который просто заменит старое значение, если только переменная уже не объявлена с помощью let
.
function func(arg) {
let arg = 1; // not ok, because `let` knows that `arg` is being redeclared
}
function func(arg) {
var arg = 1; // ok, because `var` will just replace the value of `arg`
}
function func() {
let arg = 0;
var arg = 1; // not ok, because `let` declared `arg` already
}
Вот ссылка на MDN для, которая объясняет эту функцию.
Ответ 5
Итак var
- устаревший синтаксис, и в идеале вы, вероятно, захотите его не использовать.
Вместо использования let
для переменных, которые можно переназначить, и const
для констант.
var
также имеет глобальную область действия, где let
и const
ограничены областью, в которой они находятся.
Ответ 6
Связывание параметров не точно соответствует тому же поведению, что и те, которые были объявлены с помощью let
.
1) Связи параметров создаются до привязок var
. var
не создает привязки, которые уже существуют, поэтому проблем там нет. let
однако создает привязки после var
.
2) Существует ранняя ошибка во всех продуктах, которые создают область, в которой она, как правило, не имеет никакого лексического связывания, если уже есть объявление переменной с тем же именем.
Ответ 7
Первый пример не будет вызывать ошибку значением, если аргумент передается на вызов func
.
var
не имеет той же области, что и let
или const
.