Is 'Window' Really Global in JavaScript

Is 'window' really global in JavaScript?

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.

What's the difference between a global variable and a 'window.variable' in JavaScript?

No difference. They both have the same effect (In the browser, where window is the global context1).

  • window.foo = "bar" sets the property foo on window.
  • foo = "bar" indicates either a typo or intentionally global.

Since I have to double check whether it's a typo or not, I personally find it more readable to set window.foo directly.

Also, in ES5 strict mode, foo = "bar" is an illegal assignment because foo is not declared and will throw a Error.

Edit:

As noted in the comments, foo = "bar" will look all the way up the scope chain for the variable foo and re-assign it with "bar" if it's found. If it's not found, it will create a new global variable.

Also with window.foo = "bar" you're just assigning a property to an object, which can be deleted using delete window.foo.

In ES5 strict mode it is invalid to delete a variable.


1 In other environments, such as node.js and Web Workers, there may be another name for the global object and window may not exist at all. Node.js uses global and Web Workers use self.

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

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 global variables just properties on the `window` object?

Is the window object the ultimate global object and does that have an object called window that refers back to itself?

Yes, and yes. This, for instance, returns true:

window.window.window.window.window === window.window;

You can, if you are interested, get a list of all the properties of the window object (and hence all global variables) with Object.keys:

console.log(Object.keys(window));

Note, however, that if you are spending too much time thinking about global variables, there is probably a problem with the architecture of your code.

Why are global variables added to a window object in JavaScript?

It actually is noted in the specification here, when a variable is assigned to when no such identifier exists:

If IsUnresolvableReference(V) is true, then
a. If V.[[Strict]] is true, throw a ReferenceError
exception.
b. Let globalObj be GetGlobalObject().
c. Return ? Set(globalObj, V.[[ReferencedName]], W, false).

And here, in CreateGlobalVarBinding, which is called when a variable is declared at the top level of a script.

6. Let varDeclarations be the VarScopedDeclarations of script.
...
18. For each String vn of declaredVarNames, do
a. Perform ? env.CreateGlobalVarBinding(vn, false).

The global object may be the window in a browser, or self in a web worker, or the Node global, etc.

What are the types of global objects `window` and `document`?

In JavaScript DOM, there are global objects window and document.

No, not really. The window is part of the Browser Object Model (BOM), not the Document Object Model. And the document is not a Global object, it's a property of the Global window object. The reason you can access it as just document is not because document is Global, it's because window is and because of the way the JavaScript Scope Chain works, omitting window just means that it will ultimately find document in the Global window object.

The "Core" Document Object Model is a generic API for working with XML or HTML documents and because it can be used in both kinds, the document object is not specific to an HTML or XML document.

The graphic that you are showing refers to a variant of the Document Object Model, called the HTML DOM, which takes into account elements and attributes that are specific to HTML documents, and so yes, in that graphic, HTMLDocument implements the Document interface and that means that an HTMLDocument is a type of document, but it is still also implementing the Node interface.

Now finally, we have to address types vs. instances. In JavaScript there is no window or document "type", there are "objects", which window and document are. Objects though come in many different varieties and window is an instance of a Window object, while document is an instance of a Document object:

console.log(typeof window);  // The window is a type of objectconsole.log(window instanceof Window);  // Particularly a Window object
// You can often find out what interface the object implements// by just logging it cast as a string.console.log(window.toString());console.log(document.toString());

The confusion about Global object in JavaScript

Is not pretty safe to make assumptions about the global object or the default this context, as it can vary from one javascript runtime to another, and some features like the strict mode also change this behavior.

Keep in mind that javascript not only runs in the browser -and global in node.js for instance does not work as in the browser-, and that there are a lot of different browser implementations out there.

Also, while var does write to global by default in some environments, const and let doesn't.

In node, functions called freely with no previous reference won't call them from global, but will fail instead. This heavily affects also front-end code since much of javascript for the browser nowadays is pre-compiled in a node environment via webpack etc.

So, succintly: is usually difficult to assume things about global, window and default this bindings and get them right. It is probably safer to assume that you don't have a default global object available and always refer window explicitly, as:

config.js

window.config = {foo: 'bar'}

window.someGlobalFunction = function() {...}

user.js

// do:
const elen = new User(window.config);
window.someGlobalFunction();

// don't
const elen = new User(config);
someGlobalFunction();

window.variableName

window.variableName means that the variable is being declared at the global scope. This means any JS code will have access to this variable. Using window. is not necessary but is frequently used as a convention to denote that a variable is global.

Globals are generally to be avoided. You should define variables within the scope of functions.



Related Topics



Leave a reply



Submit