What does the window object contain? - javascript

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();

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.

why don't const and let statements get defined on the window object [duplicate]

This question already has answers here:
What is the difference between "let" and "var"?
(39 answers)
Closed 3 years ago.
Let's take the following code for example:
const constVar = 'some string';
let letVar = 'some string';
var varVar = 'some string';
(function() {
console.log(window.constVar); // prints undefined
console.log(window.letVar); // prints undefined
console.log(window.varVar); // prints 'some string'
})();
According to the description of the const statement by mdn:
This declaration creates a constant whose scope can be either global or local to the block in which it is declared.
And I assume let works in the same way.
In this case, the "block" is contained within the global scope. I guess the important distinction here is that while const constVar is "globally" accessible it still doesn't define it on the window object.
Which leads me to think that global scope and the window object are disparate. Which ultimately leads to 2 questions.
Why do variables declared using the var keyword get defined on window and variables declared with const and let not defined on window?
What is the difference between "global scope" and the window object provided to us by browsers.
1. Why do variables declared using the var keyword get defined on window and variables declared with const and let not defined on window?
Because the specification says so. If you are asking for the reason behind that decision, then you should reach out to the specification maintainers.
Classes do not become properties of the global object either btw.
2. What is the difference between "global scope" and the window object provided to us by browsers.
There are two types of base environment records according to the spec:
Declarative Environment Record
Object Environment Record
A Declarative Environment Record is basically your standard environment that you get when calling a function. All bindings (variables, constants, etc) are defined in some internal data structure that cannot be accessed from normal code.
An Object Environment Record on the other hand uses an actual JavaScript object to store bindings. This is used for example by the now deprecated with statement:
with({foo: 42}) {
console.log(foo);
}
Now, a Global Environment Record actually consists of two environment records: A declarative environment record and an object environment record. The object environment is backed by the global object, i.e. window and contains var declarations and other globals that the browser provides. The declarative environment contains the let, const, class, etc declarations.
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
This declaration creates a constant whose scope can be either global or local to the block in which it is declared.
Global constants do not become properties of the window object, unlike var variables. An initializer for a constant is required; that is, you must specify its value in the same statement in which it's declared (which makes sense, given that it can't be changed later).
To answer your 2nd question, global variable can be accessed through window object. However, there is an exception for const.

A javascript 'let' global variable is not a property of 'window' unlike a global 'var' [duplicate]

This question already has answers here:
Do let statements create properties on the global object?
(5 answers)
Closed 6 years ago.
I used to check if a global var has been defined with:
if (window['myvar']==null) ...
or
if (window.myvar==null) ...
It works with var myvar
Now that I am trying to switch to let, this does not work anymore.
var myvar='a';
console.log(window.myvar); // gives me a
let mylet='b';
console.log(window.mylet); // gives me undefined
Question:
With a global let, is there any place I can look if something has been defined like I could with var from the window object?
More generally:
Is var myvar='a' equivalent to window.myvar='a'?
I hear people say that at the global level, let and var are/behave the same, but this is not what I am seeing.
I hear people say that at the global level, let and var are/behave the
same, but this is not what I am seeing.
Eh, yes and no. To answer your question, in the large majority of cases let and var are the same when declared globally, but there are some differences.
To explain: A global environment record is where JS keeps all the logic and memory values for the code in play. However, this global environment record is really a composite encapsulating an object environment record and a declarative environment record.
Some more explanation:
A declarative environment record stores the bindings in an internal data structure. It's impossible to get a hold of that data structure in any way (think about function scope).
An object environment record uses an actual JS object as data structure. Every property of the object becomes a binding and vice versa. The global environment has an object environment record whose "binding object" is the global object. This would be the Realm, which in most cases is the window object.
So, per the ECMA spec, only FunctionDeclarations, GeneratorDeclarations, and VariableStatements create bindings in the global environment's object environment record.
All other declarations (i.e const and let) are stored in the global environment's declarative environment record, which is not based on the global object. They still declare a variable, but are not a VariableStatement.
TL;DR: Both are still global, but vars are stored in the window object, while lets are stored in a declarative environment that you can't see (just like you can't access a variable in a function scope from outside of the function). When declared globally, both statements are pretty much identical in use.

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.

Is 'window' really global in 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...

Categories

Resources