When it comes to each variable declaration (not initialization!), the following process occurs (section #10.5
):
8. For every VariableDeclaration and VariableDeclarationNoIn in the code, follow these steps in sequential order according to the source text:
- Identify the Identifier in d as dn.
- Determine whether a binding for dn already exists by calling env’s HasBinding concrete method.
- If no binding exists for dn, then
- Create a mutable binding using env’s CreateMutableBinding concrete method with arguments dn and configurableBindings.
- Set the mutable binding by calling env’s SetMutableBinding concrete method with arguments dn, undefined, and strict.
Thus, whenever var x
is encountered, it checks if a variable named x
is already present in the environment. If so, it is disregarded; if not, the variable is declared and initialized with undefined
.
Since the code runs in global scope, it verifies the existence of JSON
in the global scope. Therefore, if JSON
already exists, var JSON;
is simply ignored.
Some reflections on testing/explaining this behavior:
I'm unsure exactly when the JavaScript execution creates the global object, but I presume it happens before evaluating other scripts. This implies that JSON
exists with a value even before any variable declaration, a scenario only achievable by including two separate scripts (they can be inline).
Experiment with:
// script1.js
var foo = 'bar';
// script2.js
var foo;
if(!foo) {
foo = 'baz';
}
alert(foo);
// include script2.js after script1.js
What result do you expect? (find out here).
In a single script file, all variable declarations are lifted to the top anyway. So, if you have:
var foo = 'bar';
var foo;
if(!foo) {
foo = 'baz';
}
The script essentially runs like this:
var foo;
var foo;
foo = 'bar';
if(!foo) {
foo = 'baz';
}
You cannot verify if the second var foo;
overrides the first one because it lacks a value at that point. Hence, this example doesn't effectively showcase the mentioned behavior.