Is 'window' really global in JavaScript?
Asked Answered
M

7

32

Take this piece of JavaScript code 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>
Muzzleloader answered 13/7, 2011 at 13:24 Comment(2)
No-one mentioned window is the global object all global variables are properties of window. It is the container of global objects. (Including itself window.window)Unpleasant
@Unpleasant window.windowDuffel
L
28

The reason why you can access "out of scope" or "free" variables in ECMAScript is the so-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 its 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.

Lilia answered 13/7, 2011 at 13:50 Comment(3)
Is there a way to alter the scope chain? E.g. to prevent a function from having access to the global scope?Supervene
How to access [[Scope]] property syntactically?Rooted
What is "VO"? (near "global context VO")Inexpugnable
L
18

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.

Liquescent answered 13/7, 2011 at 13:27 Comment(5)
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?Muzzleloader
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).Liquescent
@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.Handout
@Handout Until Object? Surely window is not a static property of Object...or is it?Muzzleloader
@Bart van Heukelom: Sorry, meant to write Window object.Handout
Z
9

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 specification.

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.

Zarathustra answered 13/7, 2011 at 13:52 Comment(3)
Come to think of it, window.window.window.window.window === window.window.window.window.Bukovina
When does the compiler know when to stop so that we don't have infinite window.window.window etc...?Tonneson
@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.Zarathustra
M
6

It has to do with the scope chain.

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

Manual answered 13/7, 2011 at 13:40 Comment(2)
Interesting. Looks like the global scope is indeed just a regular one, just at the highest level.Muzzleloader
Can you summarise in your answer (include the gist of it)? This resource may not stay up for ever.Inexpugnable
Z
3

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),

Zabaglione answered 13/7, 2011 at 13:57 Comment(3)
You can redefine window. (function (window) { alert(window) })(1).Bukovina
you are not redefining window in this way, you are creating a closure with an argument with name "window"... it's a different thing! :)Zabaglione
function syntax is invalid, requires a name. variable foo=2 in function f(){} is not equivalent to window.fooRooted
D
1

The window global scope applies only to the main thread. In web workers there is no window global variable. Instead you have WorkerGlobalScope inside a WebWorker and in a SharedWorkerGlobalScope inside a SharedWorker.

This worker global scope is stored in a variable called self and as MDN describes it:

this scope contains the information usually conveyed by Window objects.

This can become a problem when 3rd party code you are using in your web worker is using the window object. This can be easily solved by declaring a window variable as suggested by @FelipeMicaroniLalli in his answer here like this:

var window = self;
Doit answered 2/6, 2016 at 12:42 Comment(0)
C
0

In the book JavaScript: The Good Parts, as I understand, Douglas Crockford explains that window is the global object of the web browser that contains all the global variables. It is like the One Ring...

Conservatism answered 13/7, 2011 at 13:49 Comment(2)
What is "the One Ring"? Is it a Tolkien reference? Or something else?Inexpugnable
Yes, it is a reference to The Lord Of The RingsConservatism

© 2022 - 2024 — McMap. All rights reserved.