Let's try to transcript what ECMAScript® 2021 Language Specification says.
First, according to JavaScript: Understanding the Weird Parts there are two phases of running code: Creation Phase and Execution Phase. Conceptually it's like code is processed twice (not executed, processed).
For var a = 5;
statement this is happening:
- Creation Phase: memory allocation for identifier a and undefined value set to this memory (so called hoisting)
- Execution Phase: put value 5 into memory associated with identifier a (instead of undefined)
Now 14.3.2 Variable Statement section of ECMAScript® 2021 Language Specification says this
A var statement declares variables that are scoped to the running execution context's VariableEnvironment. Var variables are created when their containing Environment Record is instantiated and are initialized to undefined when created. Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration but those declarations collectively define only one variable. A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer's AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.
Let's examine it line by line.
Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration
In this case BindingIdentifier is just a identifier. Statement means these syntaxes are allowed officially.
var a;
var a;
var a = 1;
var a = 2;
var a, a;
var a = 1, a = 2;
but those declarations collectively define only one variable
Directly says it's the same variable, only one memory is allocated.
Conceptually you might think that if at Creation Phase variable with identifier
(a is our case) was already created, it's creation is skipped (previous statement already allocated memory and set undefined into it).
A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer's AssignmentExpression when the VariableDeclaration is executed, not when the variable is created
Just further emphasizes difference between assignment (happens at Execution Phase) and variable creation (happens at Creation Phase) of this statement
var a = 5;
Explanation
Now let's summarize what we know.
This syntax is officially supported by specification. It means only one variable is created (one memory location to hold value)
var a = 1;
var a = 2;
It has nothing to do with hoisting. Hoisting is still happening as usual.
console.log(a) // this is undefined
var a = 1;
var a = 2;
Assignments will happen at Execution Phase line by line, changing value at the same memory location.
console.log(a) // undefined
var a = 1;
console.log(a) // 1
var a = 2;
console.log(a) // 2