Is window really global in Javascript?

22,031

Solution 1

The reason why you can access "out of scope" or "free" variables in ECMAscript is the such called Scope chain. The scope chain is a special property from each Execution context. As mentioned several times before, a context object looks at least like:

  • [[scope]]
  • Variable / Activation Object
  • "this" context value

each time you access a variable(-name) within a context (a function for instance), the lookup process always starts in it's own Activation Object. All formal parameters, function declarations and locally defined variables (var) are stored in that special object. If the variablename was not found in that object, the search goes into the [[Scope]]-chain. Each time a function(-context) is initialized, it'll copy all parent context variable/activation objects into its internal [[Scope]] property. That is what we call, a lexical scope. That is the reason why Closures work in ECMAscript. Since the Global context also has an Variable Object (more precisely, **the variable object for the global object is the global object itself) it also gets copied into the functions [[Scope]] property.

That is the reason why you can access window from within any function :-)

The above explanation has one important conceptional conclusion: Any function in ECMAscript is a Closure, which is true. Since every function will at least copy the global context VO in its [[Scope]] property.

Solution 2

Is window really global in Javascript?

Yes. Unless you create a new variable called window in a narrower scope

function foo() {
    var window;
}

Inside foo we can access window, we all know that, but why exactly?

Any function can access variables declared in a wider scope. There is nothing special about window there.

Solution 3

It's all defined in ECMAScript.

The global is a Lexical environment that doesn't have an outer lexical environment. All other environments are nested within it, and is bound to a global object with properties specified by the spec.

This places the properties of the global object at the start of the scope chain, from which all other environments inherit.

ES 10.2.3 The Global Environment:

The global environment is a unique Lexical Environment which is created before any ECMAScript code is executed. The global environment’s Environment Record is an object environment record whose binding object is the global object (15.1). The global environment’s outer environment reference is null.

As ECMAScript code is executed, additional properties may be added to the global object and the initial properties may be modified.

ES 15.1 The Global Object

The unique global object is created before control enters any execution context.

Unless otherwise specified, the standard built-in properties of the global object have attributes {[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}.

The global object does not have a [[Construct]] internal property; it is not possible to use the global object as a constructor with the new operator.

The global object does not have a [[Call]] internal property; it is not possible to invoke the global object as a function.

The values of the [[Prototype]] and [[Class]] internal properties of the global object are implementation-dependent.

In addition to the properties defined in this specification the global object may have additional host defined properties. This may include a property whose value is the global object itself; for example, in the HTML document object model the window property of the global object is the global object itself.

Solution 4

It has to do with the scope chain.

Have a look at the following presentation of Nicholas C. Zakas. (starting around min 5)

Solution 5

window is the base scope of all javascript objects, and it's automatically "attached" to each variables you define, unless you use "var" before the declaration, in this case the scope of the variable it's local (that means that it's contained inside the parent function, or is otherwise global too, if you are declaring your variable outside a function block). Moreover window is defined as a constant, that is you can't redefine the window object (you will get an error saying "type error: redeclaration of const window").

so:

window.foo = 5;

it's the same as:

var foo = 5;

or:

function() {
foo = 5;
}

but:

function() {
var foo = 5;
}

in this case "foo" is local (window.foo === undefined)

Share:
22,031
Bart van Heukelom
Author by

Bart van Heukelom

Professional software developer, online games, full stack but mostly backend. Electronics tinkerer. Maker. Freelance. See LinkedIn for more details. My UUID is 96940759-b98b-4673-b573-6aa6e38272c0

Updated on January 21, 2020

Comments

  • Bart van Heukelom
    Bart van Heukelom over 4 years

    Take this piece of Javascript in a browser:

    <script>
    
    console.log(window.someThing);
    var x = 12;
    
    function foo() {
       window.otherThing = x;
    }
    
    </script>
    

    Inside foo we can access window, we all know that, but why exactly?

    • Is it some kind of special global variable?
    • Or does the "root scope" (inside the script tag) have it as an implicit local variable and is it simply "closure-inherited" as any other local variable (like x above) can be?

    And how does that concur with variables declared directly inside the script tag being set as properties of window? (Or is that not so?)

    <script>
    var x = 12;
    function() {
       console.log(window.x);
    }
    </script>
    
  • Bart van Heukelom
    Bart van Heukelom almost 13 years
    But is the scope in which window lives simply the widest scope in the scope chain, or is it a special global scope? How is it resolved internally at runtime by the Javascript engine?
  • Quentin
    Quentin almost 13 years
    As I said "nothing special" (well, that isn't quite true, since it is the default variable, but nothing special with regards to scope anyway).
  • Shef
    Shef almost 13 years
    @Bart van Heukelom: It will check if there is a variable with the same name on the local scope, if none found, it will go upwards until Object.
  • Bart van Heukelom
    Bart van Heukelom almost 13 years
    @Shef Until Object? Surely window is not a static property of Object...or is it?
  • Shef
    Shef almost 13 years
    @Bart van Heukelom: Sorry, meant to write Window object.
  • Bart van Heukelom
    Bart van Heukelom almost 13 years
    Interesting. Looks like the global scope is indeed just a regular one, just at the highest level.
  • katspaugh
    katspaugh almost 13 years
    Come to think of it, window.window.window.window.window === window.window.window.window.
  • katspaugh
    katspaugh almost 13 years
    You can redefine window. (function (window) { alert(window) })(1).
  • daveoncode
    daveoncode almost 13 years
    you are not redefining window in this way, you are creating a closure with an argument with name "window"... it's a different thing! :)
  • Shaz
    Shaz almost 13 years
    When does the compiler know when to stop so that we don't have infinite window.window.window etc...?
  • user113716
    user113716 almost 13 years
    @Shaz: It is a circular reference, so it doesn't end. The compiler only creates one reference. It just happens to be a reference back to the original object on which the reference was created. That's why you can do window.window.window... Like this: var obj = {}; obj.obj = obj;. There's only one reference created but it's a reference back to the original, so you can do obj.obj.obj.obj.obj.obj.obj === obj.
  • pseudosavant
    pseudosavant almost 11 years
    Is there a way to alter the scope chain? E.g. to prevent a function from having access to the global scope?
  • overexchange
    overexchange over 6 years
    function syntax is invalid, requires a name. variable foo=2 in function f(){} is not equivalent to window.foo
  • overexchange
    overexchange over 6 years
    How to access [[Scope]] property syntactically?