Reputation: 139
function func(x = y, y = 2) {
return [x, y];
}
func(); // ReferenceError: y is not defined
func(1); // [1, 2]
As the code above implied, there is a hidden TDZ in the function parameters scope, which explains why the code below fails:
function func(arg) {
let arg = 1; // SyntaxError: Identifier 'arg' has already been declared
}
So function parameters should be declared with let
, but what confused me is :
function func(arg) {
var arg = 1;
console.log(arg); // 1
}
this code works fine.
Why you can redeclare variables using var
? How does Javascript declare function parameters?
edit:
I know exactly you can't use let to redeclare a variable. The question here is if function parameters is declared using let
, so:
function func(arg) {
var arg = 1;
}
is like:
let arg; // arg parameter declares here
var arg = 1; // func body
and why this can run without an exception?
Upvotes: 0
Views: 521
Reputation: 14423
Parameter bindings does not exactly follow the same behavior as the ones declared with let
.
1) Parameter bindings get created before var
bindings. var
doesn't create bindings that already exist, so there's never a problem there. let
however creates bindings after var
.
2) There's an early error on all productions that create a scope that has it as a rule that no lexical binding can occur when there's already a variable declaration with the same name.
Upvotes: 0
Reputation: 665130
there is a hidden TDZ in the function parameters scope
Yes indeed. Have a look here for some more examples.
How does Javascript declare function parameters?
As parameters - see here for a step-by-step explanation. They're neither the same as let
nor the same as var
, they have their own semantics. ES6, which introduced default initialisers, gave them the same TDZ limitations as in let
to catch more programmer mistakes.
Why you can redeclare variables using
var
?
Because until ES5, redeclaring a variable was not an error condition, and this behaviour needed to be preserved to not break the web. It could only be introduced for new features, like let
and const
- or argument lists that use default initialisers, try function x(bar, bar) {}
vs function x(bar, bar=1){}
.
Upvotes: 3
Reputation: 3977
The reason that is, is because of something that people in the JavaScript community refer to as "hoisting" when you do var arg = 1
that gets translated into var arg;
arg = 1;
however if var has already been defined as is the case here because of the function parameter, then the compiler tries to be helpful and ignores subsequent re-declarations instead of throwing an error... which is probably an unexpected behaviour, and hasn't been followed through with the new let variable declaration, however, it has to stay there for backwards compatibility reasons.
Upvotes: 1
Reputation: 5293
let
is added more recently and with it, an error throw was introduced that manifests when you try to declare a variable that involves let
twice. This does not happen with var
which will simply replace the old value, unless the variable has been already declared with 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
}
Here is a link to the MDN for let which explains the feature.
Upvotes: 0
Reputation: 1647
So var
is legacy syntax and ideally you probably want to avoid using it.
Instead using let
for variables that can be reassigned, and const
for constants.
var
also has global scope where as let
and const
are limited to the scope they are in.
Upvotes: 0
Reputation: 72947
This isn't necessarily related to the function's arguments.
This will throw an error as well:
function func() {
var arg = 1;
let arg = 2
console.log(arg); // 1
}
func();
You just can't use let
to re-declare a variable, while var
isn't that strict: var
doesn't try to re-declare the variable if it's already declared. It just assigns the new value.
For more information on the specifics of let
, see this MDN page on the let
statement.
Upvotes: 1
Reputation: 1
The first example will not throw an error a value if an argument is passed to func
call.
var
does not have the same scope as let
or const
.
Upvotes: -2