3

I have read Variables and scoping in ECMAScript 6, but I still got some strange output when I execute the codes in browser console below

for(let i = 0; i < 0;) {
    var i
}//Uncaught SyntaxError: Identifier 'i' has already been declared
for(let i = 0; i < 0;) {
    let i
}//undefined

Why the first one throws an error? When I try this in parameter, it goes opposite

function foo(x){
    let x
}//Uncaught SyntaxError: Identifier 'x' has already been declared
function foo(x){
    var x
}//undefined
刘灵波
  • 41
  • 2
  • What is your actual question? Please consult the [how-to-ask](https://stackoverflow.com/help/how-to-ask) section. – StefanN Aug 06 '19 at 10:24
  • 1
    @StefanN I believe the question is fairly clear, that is, why does the first example throw an error, especially given the second set of examples – OliverRadini Aug 06 '19 at 10:28
  • 1
    First case happens because `i` is hoisted (hence already declared), second happens because `let i` is never reached, third happens because `x` is already binded to an argument, four is ok because `var`s can be redeclared if not in strict mode, if I'm not wrong. – briosheje Aug 06 '19 at 10:38

2 Answers2

2

The first sample throws because

for(let i = 0; i < 0;) {
    var i
}

is equivalent to the following code due to hoisting of var

var i

for(let i = 0; i < 0;) { // <-- throws because `i` has already defined 

}

The second sample wont throw because loop body never executes and even if it would for-loop body creates a block scope so it is ok to have another let i in it

for(let i = 0; i < 0;) {
    throw new Error('Never reached')
    let i
}

for(let i = 0; i < 2; i++) {
    let i = 'bar' // ok
    console.log(i)
}

The third sample throws because name x already binded to an agrument.

function foo(x){
    let x // throws because `x` already used
}

The last sample is ok because var can redefine names

function foo(x){
    var x
    var x
    var x
}
adiga
  • 34,372
  • 9
  • 61
  • 83
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
0

The difference is scoping. var is scoped to the nearest function block and let is scoped to the nearest enclosing block, which can be smaller than a function block. Both are global if outside any block.

Also, variables declared with let are not accessible before they are declared in their enclosing block. As seen in the demo, this will throw a ReferenceError exception.

if you want more explanation you can read the following answer with some examples for better understanding,

Community
  • 1
  • 1
SmailxCoder
  • 63
  • 10