Click to See Complete Forum and Search --> : Use of Global Variables in Functions


Thomas2
07-26-2003, 09:46 AM
I noticed that if you pass an argument to a function with an 'onClick' event handler, the argument is not known in other functions, despite being declared as a global variable in the main javascript.
Consider the following example:

<HTML>
<BODY>

<SCRIPT Language="Javascript" type="text/javascript">
<!--
var n=0;

function test(n) {
setTimeout("test2()",500);
}

function test2() {
document.write(n);
}

//-->
</SCRIPT>

<A HREF="#" onClick="test(1)">Call function for n=1</A>

</BODY>
</HTML>


Clicking on the link prints out the initial value n=0 rather than n=1 as passed throught the event handler.

Only be re-assigning the value in the first function is it known in the second function (see below)


<HTML>
<BODY>

<SCRIPT Language="Javascript" type="text/javascript">
<!--
var n=0;

function test(nn) {
n=nn;
setTimeout("test2()",500);
}

function test2() {
document.write(n);
}

//-->
</SCRIPT>

<A HREF="#" onClick="test(1)">Call function for n=1</A>

</BODY>
</HTML>



Does anybody know what is going on here ?

AdamGundry
07-26-2003, 10:13 AM
Presumably including n in the parameter list of test() redeclares it as a local variable, so within the scope of the function n has the passed value, and outside it the original value is unchanged. This is the behaviour I would expect is logical from a language which properly implements global/local variable scope.

Adam

Thomas2
07-27-2003, 04:42 AM
Originally posted by AdamGundry
Presumably including n in the parameter list of test() redeclares it as a local variable

Why should a variable assignment in the function argument be any different from an assignment in the function itself ? As far as my understanding of the Javascript syntax (if such a thing exists) goes, the variable n would only be local in a function if explicitly declared there through 'var n=...'.
Besides, if you try to pass the value of n through the function argument, it does not work either:

<HTML>
<BODY>

<SCRIPT Language="Javascript" type="text/javascript">
<!--
var n=0;

function test(n) {
setTimeout("test2(n)",500)
}

function test2(n) {
document.write(n);
}

//-->
</SCRIPT>

<A HREF="#" onClick="test(1)">Call function for n=1</A>

</BODY>
</HTML>

Clicking the link again yields zero instead of one.
More bizarrely, you can't even influence the value of n in the first function:

<HTML>
<BODY>

<SCRIPT Language="Javascript" type="text/javascript">
<!--
var n=0;

function test(n) {
n=1;
setTimeout("test2(n)",500)
}

function test2(n) {
document.write(n);
}

//-->
</SCRIPT>

<A HREF="#" onClick="test(1)">Call function for n=1</A>

</BODY>
</HTML>


This still prints out zero.
Only if you use a different variable in the first function argument, is the value passed correctly:

<HTML>
<BODY>

<SCRIPT Language="Javascript" type="text/javascript">
<!--
var n=0;

function test(nn) {
n=nn;
setTimeout("test2(n)",500)
}

function test2(n) {
document.write(n);
}

//-->
</SCRIPT>

<A HREF="#" onClick="test(1)">Call function for n=1</A>

</BODY>
</HTML>


This appears to be a bug related to the handling of function arguments. It definitely doesn't make much sense to me. Yet if you know a syntax rule that explains this behaviour I would appreciate if you could let me know.

AdamGundry
07-27-2003, 01:49 PM
Just spotted one thing which may be confusing the issue: calling setTimeout evaluates the string passed after the time has elapsed, not at the start. Thus (after the 500ms have passed) the global variable is back in scope instead of the local one.

From the JS 1.5 manual:All parameters are passed to functions by value; the value is passed to the function, but if the function changes the value of the parameter, this change is not reflected globally or in the calling function.
Try using this to see if the results are as you expect:
setTimeout("test2(" + n + ")",500)

Adam

Thomas2
07-28-2003, 04:38 AM
The time delay shouldn't make any difference as nothing happens to the variable in the meanwhile ( in fact a time delay of zero gives the same result), but your suggested form for the function call does indeed work because you split the variable from the rest of the string (it seems that Javascript has problems with interpreting nested function expressions, which forces one to do these awkward string manipulations). But this wasn't actually my initial problem which indeed seems to be explained by the passage you quoted.
Thanks for your help. I think I understand now the problems I encountered.