abs wrote:
Hi everyone.
Please, check my test code here: http://skocz.pl/jstest . The trouble is
that no matter which span element I click, it alerts '3' and I'm wondering
why not '1' for the first span, '2' for second and '3' for third ?
The values should be 0, 1 and 2.
Anybody has any idea ?
You have discovered closures - the code of interest is:
function setOnclicks() {
spans = document.body.getElementsByTagName('span')
for(i=0; i<spans.length; i++) {
span = spans[i]
span.onclick = function() {testfunction(i)}
}
}
i here forms a closure back to i in the function (which you've created
as a global, but even if you'd made it local you'd still get the same
result). When the loop finishes, the value of i is 3, so all the
onclicks show 3.
Always declare variables with var, particularly for counters like i
inside functions. Some candidates for a solution are:
function setOnclicks() {
var spans = document.body.getElementsByTagName('span')
for(var i=0; i<spans.length; i++) {
span = spans[i]
span.onclick = new Function('testfunction(' + i + ')');
}
}
But new Function is considered only marginally better than using eval.
Another way to modify the scope chain is:
function setOnclicks() {
var spans = document.body.getElementsByTagName('span')
for(var i=0; i<spans.length; i++) {
span = spans[i]
span.onclick = (function(x){
return function(){testfunction(x)};
})(i);
}
}
However I find that exacerbates IE's memory leak problem with closures
involving DOM elements - it may not be a problem for you in this case.
You can also modify the scope chain by using a function to attach the
handler:
function setOnclicks() {
var spans = document.body.getElementsByTagName('span')
for(var i=0; i<spans.length; i++) {
addOnclick(spans[i], i);
}
}
function addOnclick(el, i){
el.onclick = function(){testfunction(i);};
}
A novel suggestion by Lasse Nielsen[1] uses with:
function setOnclicks() {
var spans = document.body.getElementsByTagName('span')
for(var i=0; i<spans.length; i++) {
span = spans[i]
with ({temp : i}) {
span.onclick = function(){testfunction(temp)};
}
}
}
1. <URL:
http://groups.google.com.au/group/co...0caf593c683e27
>
There are probably other solutions, search the archives for 'onclick
closure'
--
Rob