0

I'm python developer. In python, When you want to check whether a variable is already defined, you use dict

memo = {}
if 'a' not in memo:
    memo['a'] = 'var_a'

javascript let keyword has similar functionality, it prevents re-defining.

let a = 1;
let a = 2; // SyntaxError

So how let achieves this functionality under the hood? Does V8 engine keeps some kind of HashMap of let variables?

Jerry
  • 399
  • 1
  • 2
  • 17
  • Does this answer your question? [JavaScript check if variable exists (is defined/initialized)](https://stackoverflow.com/questions/5113374/javascript-check-if-variable-exists-is-defined-initialized) – Xupitan Jun 04 '22 at 03:34
  • 3
    Yes, the JS engine does keep a list (or map or set) of the variables that are available in the current scope and where they are defined. – Bergi Jun 04 '22 at 03:40
  • 1
    `dict`s in Python and variables in Python are different things. The JavaScript equivalent of that would be more like `let memo = new Map();` `if (!memo.has('a')) { memo.set('a', 'var_a'); }`. – Ry- Jun 04 '22 at 03:52
  • https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var – Jupri Jun 04 '22 at 03:53
  • 1
    If you are interested in how this works in general, I recommend reading https://craftinginterpreters.com/ – Felix Kling Jun 04 '22 at 08:13

1 Answers1

1

Does V8 engine keeps some kind of HashMap of let variables?

Essentially, yes - though it's not a V8 thing in particular, it's something that all spec-compliant JavaScript engines must adhere to. It's called an environment record, which in this case is a "lexical environment", which is, to oversimplify, a collection of identifiers for a given scope and the values that the identifiers hold at that point.

When a function is evaluated, FunctionDeclarationInstantiation runs, which does, among many other things:

34. For each element d of lexDeclarations, do
  a. (unimportant; omitted)
  b. For each element dn of the BoundNames of d, do
    i. If IsConstantDeclaration of d is true, then
      1. Perform ! lexEnv.CreateImmutableBinding(dn, true).
    ii. Else,
      1. Perform ! lexEnv.CreateMutableBinding(dn, false).

The lexDeclarations include identifiers declared with let or const inside the function. This list cannot have duplicate entries as a result of an Early Errors requirement, which says, for blocks:

It is a Syntax Error if the LexicallyDeclaredNames of StatementList contains any duplicate entries.

Identifiers declared with vars are slightly different - they're not LexicallyDeclaredNames, but VarDeclaredNames instead, which have no requirement against being listed multiple times in a block. This doesn't result in duplicate var names being created multiple times in the environment because the duplicate declarations are explicitly skipped from the CreateMutableBinding call:

e. For each element n of varNames, do
  i. If n is not an element of instantiatedVarNames, then
    1. Append n to instantiatedVarNames.
    2. Perform ! varEnv.CreateMutableBinding(n, false).
    ...
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Is the environment record that is populated in *FunctionDeclarationInstantiatin* even relevant? The early error is thrown when the code is parsed, not when the function is called. – Bergi Jun 04 '22 at 16:25
  • It shows how and where an identifier becomes associated with a value by the engine, which I think is useful given part of the question was *Does V8 engine keeps some kind of HashMap of let variables?*, even though that section isn't where the error would occur when a duplicate name is found – CertainPerformance Jun 04 '22 at 16:28