Misleading Explanation of let variables

Tell us what’s happening:
Describe your issue in detail here.
The challenge has a statement “when using let, a variable with the same name can only be declared once.”
I think it’s misleading, there should be more about it. See the following example, we can declare the same variable into a local scope without error.
Your code so far


var catName;
let quote;
function catTalk() {
"use strict";
let quote;
catName = "Oliver";
quote = catName + " says Meow!";

}
catTalk();
  **Your browser information:**

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.62.

Challenge: Explore Differences Between the var and let Keywords

Link to the challenge:

1 Like

I’m not sure if this statement is correct at all actually. If you redeclare a variable with let even in the same scope, it won’t cause an error. I had to try this myself because I honestly couldn’t remember if this was the behaviour or not.

It’s not in the same scope. See for example:

let example = "foo"

function a() {
  let example = "bar";
  function b() {
    let example = "baz";
    function c() {
      let example = "quux";
    }
  }
}

They aren’t the same variables: they just have the same name, but the name isn’t relevant. This is the same with all identifiers. You can’t declare an identifier with the same name in the same scope, otherwise you get an error. But if it’s not the same scope, you do what you want – just to stress, just because you give things the same name, it doesn’t mean they’re the same thing. If you try to give things in the same scope the same name, then logically, the computer has no way of ascertaining what you’re trying to do (previously, with var and not in strict mode, it would take the last declared, now, much more sensibly, it errors). But if they’re in a different scope, it doesn’t care, it doesn’t store them under that name, it just uses some arbitrary address in memory. Like, as long as you only had one per scope, you could call every variable in your entire program quote, the computer cares not

2 Likes

JS creates variables as a local scope per default. However if it doesn’t find a local variable, it will move up in the scope. That’s why you can access catName within the function even without declaring it there.
Other languages will throw an error for that, unless you actively tell them to move the scope.

var catName = "Tim";
var quote;
function catTalk() {
  "use strict"
  var catName = "Oliver";
  quote = catName + " says Meow!";
  console.log(quote)
}
console.log(catName)
catTalk();
console.log(catName)
console.log(quote)

produces:

Tim
Oliver says Meow!
Tim
Oliver says Meow!

So even the flawed var does create a local-scope variable and not interfere with the variable declared on the higher scope.
Meanwhile the variable quote was declared outside but only overwritten inside - and it’s value is changed outside.

1 Like

I think it’s referring to this: 9. Variables and scoping (exploringjs.com)

But allowing declarations of variables with identical names in different scope is kind of given. Imagine what a nightmare it would be to code big programs if this wasn’t true.

1 Like

The language used in the challenge isn’t that great.

You can not redeclare a variable that is declared using let. Declaring two variables in two different scopes is not the same as re-declaring a variable. The redeclaration attempt must happen inside the same scope, otherwise, it is not a redeclaration.


I do however see some odd behavior in Chrome when compared to Firefox.

Firefox, all code entered and executed:

let camper = 'James';
let camper = 'David';
Uncaught SyntaxError: redeclaration of let camper
debugger eval code:2:4note: Previously declared at line 1, column 4

Firefox, each line entered and executed:

let camper = 'James';
undefined
let camper = 'test';
Uncaught SyntaxError: redeclaration of let camper

Chrome, all code entered and executed:

let camper = 'James';
let camper = 'David';
VM266:2 Uncaught SyntaxError: Identifier 'camper' has already been declared

Chrome, each line entered and executed (what’s up with that?):

let camper = 'James';
undefined
let camper = 'David';
undefined
camper
"David"
1 Like

I’m not sure how much sense that makes to me, I literally never write code directly into the console, but it’s a “feature” of Chrome since v80:

1 Like
  1. Add bug that violates the standard

  2. Call it a “feature”

  3. …?

  4. Profit!

1 Like

@jsdisco Thanks, for the info. Apparently, the console now runs in REPL mode.

https://bugs.chromium.org/p/chromium/issues/detail?id=1004193


I get the motivation for it, just not sure I fully agree with it. Seems like it might give the wrong impression or cause confusion. It would be nice to be able to just toggle to REPL mode when needed.

I don’t even get the motivation for it. Who tests their code by typing into the console, and what am I missing?

1 Like

I don’t think it is uncommon for people to use the console like a scratch pad, or playground. Firefox has a multi-line mode you can switch to as well.

Using the console is also pretty handy for getting access to the different web APIs (looking at properties, methods, prototypes, etc.).

It is also not uncommon to use it when teaching, which is where this change might be more of a double-edged sword.

For the most part, I use VS Code and Quokka when playing around with code. But I do still pretty frequently use the console for small tests or to easier get to the output of code for copy-pasting.

Yeah, the description could have been better. And thanks for explaining the redeclaration part. I did not knew about it.

Chrome issue is interesting. I have to try some other things as well.
And thank you for answer.

The snippets extension for chrome lets you save js in a gist, and then run it in the console. Frankly, i do this all the time to test small code-blocks.

1 Like

Thanks for the comment.

In case of let, redeclaring a variable in the same scope will produce error.

What I have read from stack overflow is var is function scoped and let, const etc are block scoped. Also tried coding some example, my conclusion is you can have the same named variable with var keyword in another function, that means it is limited to function scope. And you can have same named variable with let keyword in another block, that means it is limited to block scope.

function - What is the scope of variables in JavaScript? - Stack Overflow

Thanks for the comment. However, my concern was something else.

Thanks for the answer. If I am not wrong in strict mode declaring variables with var keyword more than once does not show any kind of error. However, you are saying it errors. I have used the following code:

"use strict"
var a = "blabla";
var a = "lalala";

Sorry, for some reason I thought it did. You wouldn’t use var anyway IRL, so not much of an issue.

Ah, but not being able to do that is incredibly frustrating. Without that, you either have to make sure to remove const/let from any code you put into the REPL (so just globals), which is a pain when copy pasting. Or you need to manually refresh the browser every time you change something (which is minorly annoying if it’s an isolated function but majorly annoying if the repl code is acting on something in the browser window scope because the current state will get nuked)

Edit cos this seems to be confusing people: you can’t redeclare let vars (or classes) in the same scope regardless of if it’s in the Chrome console or not, Chrome dev tools don’t change the semantics of the language when they evaluate code typed into the console. cf

Oh you’re right. I was trying it in the console and it doesn’t seem to cause an issue.

You also can’t switch from let to const. I’m guessing because this change doesn’t apply to const. Which seems a little odd if it really is to be seen as a “new scope”.

const test = "test";
undefined
const test = "test2";
VM198:1 Uncaught SyntaxError: Identifier 'test' has already been declared

let letter = "A"
undefined
const letter = "B"
VM90:1 Uncaught SyntaxError: Identifier 'letter' has already been declared

let letter = "A"
undefined
let letter = "B"
undefined
letter
"B"