Hi Doug,
> I don't really understand, for example why, if there is a variable
> window.myvar, some Javascript code would not be able to access it...
As far as I know, all code within the same document can access that
property; it is global to the document because it's a property of the
"window" object, which is global to the document. Offhand, I can only
think of two situations where it would be in accessible: 1. If you're
dealing with frames or iframes, those are in separate documents and
they each get their own copy of "window" with its own properties; 2.
If "window" has been hidden by another declaration called
"window" (e.g., a function with "var window" in it, or someone using
'with'), which would be a Bad Idea(tm).
> But, my question is, is there a way I can do some type of alert() and
> have it print out what scope it is executing in?
I don't know of a reliable way to do that, no. You can get hints at
it, as with seasoup's note about arguments.callee, but that won't help
you if you're executing code in the global scope or within an 'exec'.
But good news: You can always tell by looking at the source, because
in JavaScript, scope is dictated by program structure; it's not
determined at runtime.
Most of us are familiar with the concept of globals and locals:
* * * *
var a = "h";
function doSomething() {
// 'a' is a global, so this function can see it
alert(a);
}
doSomething(); // alerts "h", the current value of 'a'
a = "j";
doSomething(); // alerts "j", the current value of 'a'
* * * *
JavaScript takes this to the logical next step: Functions declared
within a scope inherit that scope and all of its parent scopes, in a
chain:
* * * *
var a = "h";
function outermost() {
var b = "e";
function middle() {
var c = "ll";
function innermost() {
var d = "o";
alert(a + b + c + d);
}
innermost();
}
middle();
}
outermost(); // alerts "hello"
* * * *
Cool, huh? Each unqualified reference is resolved by checking it
against the innermost scope and, if not found there, the next scope up
in the chain -- in this case, innermost -> middle -> outermost ->
global. To know what the scope chain looks like, we need only look at
where the functions are defined. This is the crucial bit: It's where
they're defined, not where they're called.
The program structure tells us what variables are in scope for which
functions, but as always, the *values* of those variables is
determined at runtime. It's easy enough to realize that calling
'outermost' above gives us "hello" and that that changes if we change
'a':
* * * *
outermost(); // alerts "hello"
a = "j";
outermost(); // alerts "jello" (mmmmmm, Jello)
* * * *
Simple enough, you've changed a global used by one of the inner
functions. We can also do the same thing using a parameter to
'outermost':
* * * *
function outermost(a) {
var b = "e";
function middle() {
var c = "ll";
function innermost() {
var d = "o";
alert(a + b + c + d);
}
innermost();
}
middle();
}
outermost("h"); // alerts "hello"
outermost("j"); // alerts "jello"
* * * *
Note we don't have a global 'a' anymore; it's a parameter of
'outermost'. Doesn't matter, parameters go on the scope chain just
like local variables do.
Where people start to get a bit glassy-eyed is when we start passing
around function references, which we do all the time in JavaScript.
Consider this:
* * * *
function outermost(a) {
var b = "e";
function middle() {
var c = "ll";
function innermost() {
var d = "o";
alert(a + b + c + d);
}
innermost();
}
return middle;
}
* * * *
Note that 'outermost' now returns a reference to the 'middle'
function, it does *not* call it. No alert occurs if we call
'outermost'; it occurs when we call the function returned by
'outermost'. Now, what do we see when we do this:
* * * *
var f1 = outermost("h");
f1();
* * * *
We call 'outermost' with an "h", and it returns a function reference
we store in 'f1', and then we call the function. Well, you probably
said it alerts "hello" -- and you'd be right! How 'bout this:
* * * *
var f1 = outermost("h");
var f2 = outermost("j");
f1();
f2();
* * * *
What do we see when 'f1' is called? And 'f2'? The answers, as you
will have realized, are of course "hello" and "jello", respectively.
This is because a function reference includes the execution context of
that function, including the parameters and locals.
"Now hang on a minute," you're saying, "that parameter I passed into
'outermost' the first time is gone by the time I call 'f1'! How can
'f1' still reference it?!" The answer is: The parameter is not
gone. It would be, if there were no outstanding references to it, but
there *is* an outstanding reference to it -- our 'f1' variable refers
to it. That 'a' parameter lives on as a property of an object (called
the "variable object") within the execution context we're referencing
with our 'f1' variable. It will continue to live on until/unless we
release it. (The variable object has no symbol associated with it,
it's anonymous within code. With one exception: The topmost variable
object is the global object, which in browser-based implementations is
known as "window" [more technically, it has a property called "window"
that refers to it].)
This execution context and variable object stuff is why JavaScript
functions are technically termed "closures" (a term from mathematics
basically meaning a function that has data bound to it).
I've done a couple of blog posts on the subject -- with diagrams --
which can be found here; they may be useful:
http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html
http://blog.niftysnippets.org/2008/03/closures-by-example.html
HTH,
--
T.J. Crowder
tj / crowder software / com
Independent Software Engineer, consulting services available
On Feb 11, 1:21 am, doug <[email protected]> wrote:
> I have read about Javascript and scope and I still don't really
> understand it completely, particularly when it comes to Ajax.Updater.
>
> I don't really understand, for example why, if there is a variable
> window.myvar, some Javascript code would not be able to access it, and
> instead it would be undefined for that code. I was thinking
> window.myvar was "global"
>
> But, my question is, is there a way I can do some type of alert() and
> have it print out what scope it is executing in?
>
> thanks,
> -d
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Prototype & script.aculo.us" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~----------~----~----~----~------~----~------~--~---