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 propertyfoo
onwindow
.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 var
s are stored in the window
object, while let
s 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 calledwindow
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
How to Listen for a Click-And-Hold in Jquery
How to Verify Jquery Ajax Events with Jasmine
How to Replace a Regex Substring Match in JavaScript
When to Use the Double Not (!!) Operator in JavaScript
How to Configure Different Environments in Angular.Js
Auto-Refreshing Div with Jquery - Settimeout or Another Method
Twitter Bootstrap Alert Message Close and Open Again
How to Create a Jquery Clock/Timer
Baking Transforms into Svg Path Element Commands
How to Catch Exceptions Thrown in a JavaScript Async Callback
How to Create a Custom Error in JavaScript
Unsafe JavaScript Attempt to Access Frame with Url
Aggregation Filter After $Lookup
Convert an Image into Binary Data in JavaScript
JSON Left Out Infinity and Nan; JSON Status in Ecmascript
JavaScript Return Number of Days,Hours,Minutes,Seconds Between Two Dates