0
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?

4
  • 2
    var is legacy syntax, but let is new. It's just a quirk. Commented Oct 11, 2017 at 14:46
  • 1
    stackoverflow.com/questions/762011/… Commented Oct 11, 2017 at 14:47
  • 1
    You should not redeclare function parameters, they are already declared when entering the function body. Commented Oct 11, 2017 at 14:48
  • @Pointy I think you are the only one understand the question here and maybe this was because V8 has to compatible with ES5. But still have to confirm with someone really into V8. Commented Oct 11, 2017 at 15:32

7 Answers 7

3

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){}.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

4 Comments

Yeah, I'm confused on why this got downvoted too... (You could add a link to the documentation stating this though)
In my question, I think parameters are declared using let, so the question is like why let arg ; var arg = 1; should throw an exception but not?
@George: Thanks. I added a link.
@jerrypy: It doesn't matter if the parameters are declared using let or var, internally. For re-declaration, all that matters is that the variable is already declared.
1

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.

Comments

0

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.

Comments

0

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.

2 Comments

if you declare a variable using let first ,then redeclare it with var, it can't replace the value. let arg; var arg = 1; this will throw an exception.
Interesting, did not know that, I updated the answer.
0

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.

Comments

-2

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.

5 Comments

This doesn't answer why the let re-declaration throws an error, while using var to do the same doesn't.
@Cerbrus Because arg is already defined, arg = 1 will not throw an error. A variable declared using let or var can be set to a new value. A const declaration cannot be re-defined or deleted.
This question isn't about assignment. It's about declaring it a second time.
@Cerbrus "This question isn't about assignment. It's about declaring it a second time." ? Unless you are OP or clairvoyant you cannot conclusively state what the question is "about". The Question covers several topics

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.