The necessity of property window.window
comes from the way Javascript references its variables. Every time an expression is created involving a identifier (i.e. a name) to engine do JS searches on a special object - called Variable Object - by the key corresponding to that identifier. (this object is probably named for its function: an object that stores variables)
console.log(x + 1); // Procura por <<Variable Object>>['x']
// e depois por <<Variable Object>>['console']
When the code to be executed is in top-level, Variable Object is equivalent to Global Object (that, in the browser, would be the window
, but in other environments may be different). Ie:
console.log(x + 1); // Procura por window['x']
// e depois por window['console']
When this code is inside a function, Variable Object is called Activation Object, and is different for each function invocation:
function foo() {
console.log(x + 1);
}
foo(); // Procura por <<Activation Object 1>>['x']
// e depois por <<Activation Object 1>>['console']
foo(); // Procura por <<Activation Object 2>>['x']
// e depois por <<Activation Object 2>>['console']
The programmer does not have direct access to the Activation Object, only indirectly through the attempt to access a property by name. An Activation Object defines a execution context, that is, a set of variables that are accessible to be used by that code snippet. An execution context can "inherit" from another context, which it can inherit from another, and so on (for more details, see that my other answer in the question "How closures work in javascript?"). Example:
function foo() {
var x;
function bar() {
console.log(x + 1);
}
bar();
}
foo(); // Procura por <<Activation Object "bar" 1>>['x']
// ... <<Activation Object "foo' 1>>['x'] (encontrou)
// e depois por <<Activation Object "bar" 1>>['console']
// ... <<Activation Object "foo" 1>>['console']
// ... window['console'] (encontrou)
Well, in possession of this explanation, I ask: what happens when we simply write:
window
// ou
function foo() {
window
}
foo();
? The Javascript engine will do what it always does when it finds an identifier: search in Variable Object:
window // Procura por window['window']
function foo() {
window
}
foo(); // Procura por <<Activation Object "foo" 1>>['window']
// ... window['window'] (encontrou)
That is: so that the programmer can access the Global Object (window
), he needs to have a reference to himself (window['window']
or simply window.window
). The same goes for Node.js (global.global
) and for any other Javascript implementation that exposes the global object to programmers (whether this is mandatory or not according to the Ecmascript specification, I have not checked).
The variable self
(global) also refers to the object window
, in accordance with the specification of W3.org. What about top
, she may or may not refer to window
, as explained by @Hernandes.
Source: most of this response was based on the article (in English) "Understanding delete".
+1 because I think it answers the question better, but I would +10 for the link to "Understanding delete". There are some points in the answer that I found a little confusing, but I can’t say anything because most of the time I’m a confused person. Anyway, it is very worth reading this article in English.
– utluiz
Excellent! Just one detail: this kangax article (all of it great, right?) is a little outdated, uses the terminology of Ecmascript 3. In ES5, variable Object and Activation Object are now treated as declarative Environment Records.
– bfavaretto