On May 17, 8:44*am, Eleandor <vanbeurden.b...@gmail.com> wrote:
> Well, I realise it's not so much a bug as it is a feature.
>
> I've written a quick testpage:
>
> <html>
> * * * * <head>
When posting code, indent using 2 (preferred) or 4 spaces and manually
wrap at about 70 characters, see below.
<head>
<script type="text/javascript">
Person = (function() {
return function() {
var self = this;
this.messages = function() {
for(var i = 0; i < 10; i++) {
var elm = document.createElement("div");
elm.innerHTML = "Display " + i;
elm.onclick = function() {
self.shout(i);
};
document.body.appendChild(elm);
}
};
this.shout = function(number) {
alert(number);
};
};
}());
function LoadPage() {
var p = new Person();
p.messages();
}
</script>
</head>
<body onload="LoadPage()"></body>
>
> The html page shows "Display x" with x a number from 0 to 9. However,
> as I click it, it displays 10 regardless of which element I clicked. I
> can understand why, since the value of i is 10 when the loop ends. But
> what I'm trying to achieve is to create a function that uses the
> actual value of i, at the moment when the onclick function is created.
> So "Display 5" should actually display 5, using the literal value of i
> when the function is created, instead of the value of i at the time of
> execution.
>
> How can I achieve something like this?
You need to break the closure. One way is to use new Function, but
scope becomes a bit tricky. Another is to use a setter for the onclick
property rather than a function expression, e.g.
elm.onclick = setOnclick(self, i);
then add:
function setOnclick(self, i) {
return function() {
self.shout(i);
}
}
as a global function, or inside the outer Person function (the
Cornified one[1]).
Another is to set it with a function expression:
elm.onclick = (function(number) {
return function() {
self.shout(number);
};
})(i);
But this whole thing seems quite convoluted. The i property doesn't
seem to belong to a "person", it belongs to the listener attached to
the element, so probably shouldn't be inside the person constructor at
all. Perhaps you are better to create a message cache and use an
attribute of the HTML element to associate with a message (e.g. its
ID). If HTML 5 was widely implemented, you could add the index as a
data property of the element directly (but it will be a long time
before that is viable on the web).
There are many other solutions, hard to say what is better or worse
without knowing what you are really trying to do, I doubt that either
of the above suggestions are the best you can do in your circumstance.
1. <URL:
http://groups.google.com/group/comp....ec4b30a4e2811#
>
--
Rob