Is 'window' really global in JavaScript? - javascript

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>

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.

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.

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.

It has to do with the scope chain.
Have a look at the presentation of Nicholas C. Zakas (starting around 5 minutes).

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

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;

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

Related

A Few Questions About the Global Object

A global object is an object that always exists in the global scope. In JavaScript there is always a global object defined.
Can there be more than one global object? Why do people say Window is a global object when MDN doesnt say this?
Every browser window has a single top level Window object routinely referred to as global object. The global object is accessible via window variable.
The object exposes a number of properties, most importantly document which is also an object, methods, and events.
A developer may define (via script) variables (var) and functions which automatically become properties and methods of window (global) object (provided they are declared on top (global) level).
For example, an expression var a = 1; declares a variable named a (and assign numeric value to it). This variable is accessible by its name (a) and as well as window.a and window['a'].
The reference to the global window object can be omitted so window.a = 2; and a = 2; are equivalent (but not ['a'] = 2; which is syntax error).
Also note that global window object belongs to the browser window, not to javascript. The browser only expose it to Scripting Engine.
This is javascript basics.
I hope this explanation clears a little your confusion.

What does the window object contain?

I was exploring the this keyword in the global scope, and discovered that this in that context refers to the window.
I logged the value of this to the console, and saw a huge list shown in the image below.
What does the list I'm seeing contain, and how is it populated?
First, a brief definition for readers of what a lexical environment is, as well as how it relates to the global environment, and in turn how the global environment relates to the global object.
A lexical environment consists of:
an environment record, which stores the identifier bindings created within the scope of the environment,
a reference to an outer environment, and
references to any environments contained within.
Lexical environments inherit variable definitions declared in the environments they are contained within, and are created each time a function declaration, a block statement, or a catch clause of a try statement is evaluated. Variable definitions are not accessible outside the lexical environment they were defined in.
The following example:
defines a global variable using a var declaration, initialized to a function expression, which creates a new lexical environment,
defines a variable in the new environment, again using a var declaration, this time initialized to a string value, and
demonstrates that the variable is not accessible outside of the environment it is defined in:
var hello = function() {
var world = "fubar";
console.log(world); // "fubar";
}
console.log(world); // ReferenceError: world is not defined
The global environment is a lexical environment whose outer environment reference is null, and which includes an associated global object whose properties provide some of the global environment's identifier bindings, specifically excluding variables defined using let or const declarations, as well as other possible exclusions.
var hello = "world";
console.log(hello, window.hello); // "world", "world"
let foo = "bar";
console.log(foo, window.foo) // "bar", undefined
Now, to answer your question in context:
What does the list I'm seeing contain, and how is it populated?
The list you are seeing contains the properties of the global object, which consists of:
prepopulated identifier bindings supplied by the browser - some of which are standard, others are specific to the JavaScript engine or browser implementation -
global variables set by scripts running on the current page, or
global variables set by browser extensions you may have installed.
The information contained in this answer should conform to the ECMAScript 2015 Language Specification, which also contains definitions for most of the terms used here, and I strongly encourage you to skim over that document any time you're in the mood for some light reading.
If you find a discrepancy between this answer and the ECMAScript Language Specification, please feel free to edit this answer to conform.
These are all the functions that are part of the window object.
Think of it this way. All functions are part of an object. 'this' in running code returns the object context that the function is running in. It may be the object that the function was defined under, but 'this' can be dynamically changed in code, so more accurately its the object context that the function is running in.
window is the global object in a browser, so when you're not inside a function that is part of a sub-object to window, you are in the window object context.
for instance,
var o = { test: function(){ alert(this) } }
o.test();
will alert the o object, not window.
You can call functions directly that are in the same context, which is why you can type Infinity in the console, and it returns Infinity which is part of window.
JavaScript will also look up parent objects (window in this case) to the declared object as well, so in your browser console, this works:
var o = { test: function(){ alert(Infinity) } }
o.test();

Are the terms "global property" and "global variable" synonyms?

The global object serves as the top-level lexical environment (the top of the scope-chain, if you will). This means that global properties may be accessed via direct references (like variables):
// global code
this.foo = 1; // creating a global property
foo // accessing the global property via a direct reference
This also means that global variables may be accessed via property references:
// global code
var foo = 1; // creating a global variable
this.foo // accessing the global variable via a property reference
INTERPRETATION 1
Now, based on the above information, it would seem that it would be appropriate to use the terms "global variable" an "global property" interchangeably, meaning that both terms represent the exact same set of global bindings.
However, there are two differences between a global variable created using var ,e.g. var foo = 1;, and a global property created through an assignment, e.g. this.foo = 1;:
Global variables are statically scoped, whereas global properties are dynamically added to the global environment:
foo // => undefined
bar // throws ReferenceError
var foo = 1;
this.bar = 1;
So, global variables are bound before program evaluation, whereas global properties are bound during program evaluation, when the assignment is evaluated.
Global variables are non-configurable, i.e. they cannot be deleted (more specifically, their corresponding bindings cannot be removed from the environment subsequently), whereas global properties created through assignment are configurable.
// the names "foo" and "bar" are bound to the global environment
var foo = 1;
this.bar = 1;
// the binding "bar" can be removed from the global environment subsequently
delete this.bar;
// the binding "foo" cannot be removed subsequently
That being said, it should be noted that it is possible to create non-configurable global properties:
Object.defineProperty( this, 'bar', { value: 1 }); // non-configurable by default
INTERPRETATION 2
Now, based on this new information, one could say that only statically scoped global bindings may be referred to as both global properties and global variables, whereas dynamically added global bindings are merely global properties, but not global variables, meaning that the term "global variable" represents a subset of the set represented by the term "global property", as in:
All global variables are global properties
Only statically scoped global properties are global variables
So, which interpretation is correct? Do both terms represent the same set of bindings, or is one a subset of the other?
THE QUESTION
I do understand the term "global property" - a global property is a property of the global object. However, the term "global variable" appears to be ambiguous. Some use it as a synonym for "global property", while others define it to mean a global property which has been defined via a var statement. The intent of my question is to determine which of these two meanings is correct
Well, you already know everything I would have said to differentiate between the edge-cases of variables and properties which are attached to window.
If you wanted to get really, really pedantic, I suppose that you could consider the global scope to be both a functional-scope and a scope in which the window object is extended with properties using the same hidden configuration settings as what is provided within the program (eg: vars can be reassigned but not deleted). So in that sense, as far as functionality is concerned, they are different, and reflect attributes of properties and variables, globally scoped.
And referring to them as such is totally fine.
But the majority of people out there don't even recognize the difference, let alone differentiate between the two terms.
Even the important JS authors out there have referred to setting a global variable accidentally, by omitting var, when really, JS scales the function scopes, and if it makes it to the global scope without hitting that name, it appends a global property with that data, rather than a global variable.
But that really sort of brings us to the crux -- a strong and stable and reliable JS application, living on a modern webpage along with other applications, really shouldn't be too concerned with the differences.
The goal is to use as few global properties and variables as possible, in that case.
Moreover, the danger of variable/property collision is the same, regardless of which it is.
Variables are immune to delete, but what are the chances that any useful program is going to delete a property it's never even set?
So personally, I think it's good to understand the edge-cases, but I also think that while the pedant in me wants to agree that there's a difference, and they are not coterminous, the pragmatist in me shudders to think of a world where people are actively using the global scope to the extent where this makes a large difference to them.
A good explanation can be found here, but I'll shorten it down to answer your question. When you say:
both terms represent the exact same set of global bindings.
...you're almost correct, but not quite. Property assignments like this.foo = 1 are saved into the global object. Variable declarations like var bar = 2 however are saved into the variable object.
When executing under global scope, both the global object and the variable object are represented by the same object--the global object (when you're executing in a browser, this is the window object).
I mention this because your explanation alone is insufficient to explain the behavior of this program:
// "this" refers to the global object. But global object is also acting as the
// variable object! Because of that, the following code works:
var foo = 1;
alert(this.foo); // 1
(function() {
// "this" still refers to the global object! But the *variable* object has
// changed because we're now in the execution context of a function, thus
// the behavior changes:
var bar = 2;
alert(this.foo); // 1
alert(this.bar); // undefined
})();
This doesn't mean that global properties and global variables are identical however. There are three hidden flags on all properties: ReadOnly, DontEnum, and DontDelete.
When using implicit property declarations like this.foo = 1, the DontDelete attribute is set to false. When you use variable declarations like var bar = 2, the DontDelete attribute is set to true, thus representing the difference between them when you use the delete operator.
In response to your rephrased question:
[T]he term "global variable" appears to be ambiguous. Some use it as a
synonym for "global property", while others define it to mean a global
property which has been defined via a var statement. The intent of my
question is to determine which of these two meanings is correct.
The term is not clearly defined, and therefore you are asking for nothing more than an opinion.
In general, the term "global property" is used when you create a variable using the syntax this.foo = 1, and the term "global variable" is used when you create a variable using the syntax var bar = 2. There's nothing more to discuss.
Neither term has a true bearing on what goes on behind the scenes, thus the best you can do is understand what actually goes on behind the scenes, which you have already done.
Further demanding an absolute definition on two arbitrary terms will simply cause you to be an unpopular person.

Activation and Variable Object in JavaScript?

Is the term "activation object" just another name of "variable object" or is there actually any difference between them? I have been reading a few JavaScript articles about how variable scopes are formed in an execution context, and from my point of view it seems that in most of the articles they use these two terms interchangeably.
Well, I just learned something :). From this article, it would appear that within the execution context of a function, the Activation Object is used as the Variable Object:
When an execution context is created a number of things happen in a defined order. First, in the execution context of a function, an "Activation" object is created. [...]
Then the process of "variable instantiation" takes place using an object that ECMA 262 refers to as the "Variable" object. However, the Activation object is used as the Variable object (note this, it is important: they are the same object). Named properties of the Variable object are created for each of the function's formal parameters, and if arguments to the function call correspond with those parameters the values of those arguments are assigned to the properties (otherwise the assigned value is undefined).
However, when you're in the global scope, there isn't an Activation Object, so the Global Object is used as the Variable Object instead:
The global execution context gets some slightly different handling as it does not have arguments so it does not need a defined Activation object to refer to them. [...] The global object is used as the Variable object, which is why globally declared functions become properties of the global object.
So it sounds like "Activation Object" and "Variable Object" are the same thing within a function context, but not within the global context.
An activation object is the uppermost object in a scope-chain with the lowermost being global object.
Whereas variable object is abstract concept and therefore, depending on its execution context, is any link in scope-chain including activation/global object.
It contains:
all the variables and functions you declare inside the function body;
arguments named as specified by the function signature;
arguments as an object named arguments (in case you want your function to support multiple signatures).
It doesn't contain:
this (as it's not a variable);
named function expressions.
Further info - JavaScript. The core.
Few quotes in case of tl;dr:
A variable object is a scope of data related with the execution context. It’s a special object associated with the context and which stores variables and function declarations are being defined within the context.
A variable object is an abstract concept. In different context types, physically, it’s presented using different object.
[..] in the global context the variable object is the global object itself [..]
[..] a function’s variable object is the same simple variable object, but besides variables and function declarations, it also stores formal parameters and arguments object, and is called the activation object.
[..] when accessing this in a code, its value is taken directly from the execution context without any scope-chain lookup.
It's more accurate to say that an Activation object is a type of Variable object. This is similar to how a man is a type of HUMAN. As stated here, the term 'Variable object' is just a GENERALISED term used to describe any object that holds the properties that describe the environment and scope of the currently executing context.
Hence, within the global executing context (i.e., outside of any functions), it ends up being the Global object. Why? Because it’s the object that holds the properties that describe the environment and scope of the global executing context.
Whereas within the function local executing context (i.e., within a function), it is the function local object (a.k.a the Activation object) that is the Variable object, as it's the object that holds the properties that describe the environment and scope of the currently executing function. Properties such as function arguments for example.
An activated object just means an object that represents an element on a web page that an event occurred on. So if an image is clicked, the JavaScript object that represents that image is the activated object.

Is 'window' always on top of the scope chain in javascript?

I've seen global variables defined with window.global_name.
I wonder why not just using global_name even if this script will be run in closure.
UPD: seems like IE doesn't explicitly add it to the window object, when you declare it inside of a closure
The last object on the scope chain in any ECMAScript environment is always the global object. In browsers, window is to all intents and purposes the global object. If you want to access a property of the global object x or a global variable x (which are almost but not quite the same thing), you should explicitly qualify it with window.x to avoid the possibility of x being resolved as a property of another object on the scope chain, or globalObj.x if you care about portability to non-browser environments. You can get a reference to the global object from anywhere in ECMAScript 3 or non-strict ECMAScript 5 as follows:
var globalObj = (function() { return this; })();
window.x is safer than simply x if there might possibly be another x in the current or preceding scopes. That being said, even window isn't fool-proof because you could define a variable named window.
They have similar effects, but window lets you explicitly declare that you're deliberately using a global. Otherwise, the reader doesn't know whether it's a var further up the scope chain, you just forgot to declare it, etc.
Unless you introduce another scope, e.g. by wrapping your code in a function, window === this === <the global scope>
However, window and this have the advantage that you can use the array syntax (window['something']) so you can access globals even if you have their name only in a string without using evil things like eval.
The answer is yes. If you declare a variable without the var keyword (inside a function), the variable will become implicitely a member of the window object, that is automatically initialized by the browser.
Outside a function, with or without the var keyword, the variable becomes implicitely a member of the window object.

Categories

Resources