Hi,
> So if I'm inside an anonymous function, can I
> still use window...
Yes if the functions in question are declared at global scope (as in
Pranav's example), no if they aren't (you can access `window`, but the
functions won't be properties of it).
So this would work:
function foo() {
}
var x = 'foo';
window[x]();
but this would not:
function bar() {
function foo() {
}
var x = 'foo';
window[x](); // fails, no "foo" prop on `window`
}
The reason it works at global scope (technically, in the global
execution environment) is that the global execution environment has a
unique feature: `var`s and function declarations at global scope end
up as properties on the global object, which is accessible as `window`
in browsers (and accessible in a similar way in non-browser
environments). Although there is (at least conceptually) a similar
object in the second example that has a "foo" property, we have no way
of accessing that object directly.
If you're interested, I've given a very high-level overview of the
details below (there's still a fair bit of hand-waving; the ECMAScript
spec is 252 pages long for a reason).
So, the global execution environment has a unique feature that lets us
get at the variables defined at global scope. Before we can talk about
how that happens, we have to talk about "variable environment" object:
Consider this code (which is at the top level, not in any function):
* * * *
var global = "Hi";
function foo() {
var fooLocal = "there";
alert(global); // "Hi"
alert(typeof bar); // "function"
alert(typeof barLocal); // "undefined" because it's not in scope
function nifty() {
var niftyLocal = "!";
alert(global + " " + fooLocal + niftyLocal); // "Hi there!"
}
}
function bar() {
var barLocal = "flibbergibbet";
}
* * * *
You can think of the above is a bunch of boxes containing boxes:
+-- window ---+
| |
| +-- foo --+ |
| | | |
| | +-- nifty + | |
| | | | | |
| | | | | |
| | +-+ | |
| | | |
| +-+ |
| |
| +-- bar --+ |
| | | |
| +-+ |
| |
+-+
Without delving too much into the mechanics of it, when you call `foo`
(for instance), the interpreter creates a "variable environment"
object for the call. This object gets assigned properties for all of
the `var`s in the function, all of the named functions declared within
the function, all of its declared arguments, and the `arguments`
property. So if you call `foo`, its variable object would have these
properties:
- arguments
- fooLocal
- nifty
If you call `nifty`, its variable object would look like this:
- arguments
- niftyLocal
Unqualified references within the function are resolved by looking
them up on the variable object. So within `nifty`, if I refer to
`niftyLocal`, it's found on `nifty`'s variable object. But what if I
refer to `fooLocal`? It's not on `nifty`'s variable object, and so the
interpreter looks for the next variable object in the chain, which is
`foo`'s. And there's `fooLocal`, so we're done. If `nifty` refers to
`global`, it's not found on `nifty`'s variable object, and it's not
found on `foo`'s, so how does it get resolved?
It gets resolved because functions aren't the only things with
variable objects; the master call to the global code that ran the page
also has a variable object, and so the chain continues with that one.
Since that variable object has `global` on it, it's resolved.
E.g., when calling `nifty`, its identifier resolution chain looks like
this:
`nifty`'s variable object
-> `foo`'s variable object
-> the global environment's variable object
(It's actually a bit more complicated than that, but the complications
are not relevant here.) I give a marginally better picture in my blog
post here.[1]
Now, these variable objects are anonymous (in fact, in any given
implementation they may just be conceptual, not real). There's no way
to get a reference to the variable object for a given call to `foo`,
it's just not a specified part of the language. (The `arguments`
object gives you a very, very limited view into the variable object,
but that's it.)
EXCEPT! Remember that unique feature of the global execution
environment? Here it is: Its variable object effectively *is* the
global object. And in browsers, the global object has a property
called "window" that it uses to refer to itself. And so we have direct
access to the variable object for the global executi