Global JSON variable override

javascript, json, scope

Solution

For each variable declaration (not initialization!). The following happens (section `#10.5`):

8. For each VariableDeclaration and VariableDeclarationNoIn d in code, in source text order do

- Let dn be the Identifier in d.

- Let varAlreadyDeclared be the result of calling env’s HasBinding concrete method passing dn as the argument.

- If varAlreadyDeclared is false, then

- Call env’s CreateMutableBinding concrete method passing dn and configurableBindings as the arguments.

- Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.

So you see, whenever `var x` is encountered, it is tested whether a variable with name `x` already exists in the environment. If yes, it is just ignored, but if not, then the variable is declared and initialized with `undefined`.

Since the code is run in global scope it tests whether `JSON` exists in global scope. So if `JSON` already exists, `var JSON;` is just ignored.

Just some thoughts regarding testing/explaining this behaviour:

I don't know at which point in the JavaScript execution the global object is created, but I assume before all other scripts are evaluated. That means, `JSON` exists and has a value before any variable declaration, something you can only simulate if you include two scripts (can also be inline I guess, they are evaluated after another).

Try:

// script1.js
var foo = 'bar';

// script2.js
var foo;
if(!foo) {
    foo = 'baz';
}
alert(foo);

// include script2.js after script1.js

What's the result? (cheaters look here).

Whenever you are in a single script file, all variable declarations are hoisted to the top anyways. So if you have

var foo = 'bar';
var foo;
if(!foo) {
    foo = 'baz';
}

the script is actually executed as:

var foo;
var foo;
foo = 'bar';
if(!foo) {
    foo = 'baz';
}

You could not actually test whether the second `var foo;` overwrites the first one, since at this point it has no value yet. So this is not a good example to demonstrate the behaviour quoted above.

Problem

I had to use json2.js in my project as browser(IE8) JSON object was not available for parsing strings to JSON. I ran through json2.js and am having a doubt with the variable declaration. A JSON global variable is declared in json2.js like ``` var JSON; if(!JSON){ JSON={}; } ``` What is the effect of declaration `var JSON;` on the global JSON object. I hope the declaration should override the global JSON object in any browser (IE8/IE7). But for my surprise it is not overriding when a global object is available. Only a variable definition / initiation overrides a global variable? Kindly clarify.

Original source