Dynamically generated functions not behaving as expected...

M

mshiltonj

I've narrowed an issue down to a particular test case. I'm dynamically
adding functions to objects in a loop and trying embed certain data in
the function. The problem is that the function seems to apply the data
that existed in the last iteration of the loop to all previous
iterations. I've narrowed down an example to less than fifty lines.
The code assumes you have the FireBug extension running on FireFox...

<html>
<head> <title></title>
<script language="javascript">

var ary = new Array('a', 'b', 'c');
var objs = new Array();

var o1 = new Object();
o1.name = 'foo';
objs.push(o1);

var o2 = new Object();
o2.name = 'bar';
objs.push(o2);

var o3 = new Object();
o3.name = 'baz';
objs.push(o3);

for (idx in objs)
{
obj = objs[idx];
console.debug(obj.name);
console.debug(ary[idx]);
var func = function(name){
console.debug(name);
console.debug(ary[idx]);
console.debug(obj.name);
}
obj.func = func;
}

console.debug('-----');
o1.func(o1.name);
console.debug('-----');
o2.func(o2.name);
console.debug('-----');
o3.func(o3.name);
</script>
</head>
<body>
</body>
</html>

And the output to the firebug console is:


foo
a
bar
b
baz
c
----
foo
c
baz
-----
bar
c
baz
----
baz
c
baz

The second and third lines of each block between the line (except the
first block) is:
c
baz
But I was expecting the word ('baz') to match the first work in the
block. (i.e. 'foo')

I'm doing something wrong, or have a different expectation of the way
anonymous functions work in javascript. Can someone tell me where I'm
doing the wrong thing, and what is the proper way to achieve this
affect -- creating dymamic functions with varied data while iteration
over a loop? In my non-test code, I am unable to pass in variables to
the function call.

Thanks for any input.
 
R

Richard Cornford

mshiltonj said:
I've narrowed an issue down to a particular test case. I'm
dynamically adding functions to objects in a loop and trying
embed certain data in the function. The problem is that the
function seems to apply the data that existed in the last
iteration of the loop to all previous iterations.
The second and third lines of each block between the line
(except the first block) is:
c
baz
But I was expecting the word ('baz') to match the first work
in the block. (i.e. 'foo')

I'm doing something wrong, or have a different expectation of
the way anonymous functions work in javascript.
<snip>

See:-

<URL: http://jibbering.com/faq/faq_notes/closures.html >

- and observe that the closure that belongs each function you create is
an association between the function object and the scope chain of the
scope in which it was created, not the state of the values of the
objects on that scope chain. As the association is with the scope chain
and not the specific values the values you actually get are those that
represent the state of the objects on the scope chain at the end of the
loop, when you stopped modifying them.

The solution (or at least one solution) is to create the functions in a
way that will give each its own (unique) scope chain. You can do this by
creating a separate function that will return the function you want to
use and take the values that are of interest as its arguments

for (idx in objs){
obj = objs[idx];
console.debug(obj.name);
console.debug(ary[idx]);
obj.func = getTheFunction(ary, idx, obj);
}

//--------------------- elsewhere ----------------------------

function getTheFunction(ary, idx, obj){
return (function(name){
console.debug(name);
console.debug(ary[idx]);
console.debug(obj.name);
));
}

Richard.
 
M

mshiltonj

I've narrowed an issue down to a particular test case. I'm dynamically
adding functions to objects in a loop and trying embed certain data in
the function. The problem is that the function seems to apply the data
that existed in the last iteration of the loop to all previous
iterations. I've narrowed down an example to less than fifty lines.
The code assumes you have the FireBug extension running on FireFox...
[snip]

I'm doing something wrong, or have a different expectation of the way
anonymous functions work in javascript. Can someone tell me where I'm
doing the wrong thing, and what is the proper way to achieve this
affect -- creating dymamic functions with varied data while iteration
over a loop? In my non-test code, I am unable to pass in variables to
the function call.

Thanks for any input.

Thanks to Richard and Manish. Problem solved.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top