PDA

View Full Version : Can I force Javascript to pass a function parameter by value (not by reference)?


oheso
03-02-2010, 10:45 PM
Standing on the shoulders of giants, I have a javascript which loops through all anchors in a website and assigns a function to those with a given "rev" value. It's working quite well but I want to extend it. I'm trying to pass an array value based on a counter. Here's the code:

function image_pops_init()
{
if(document.getElementById && document.createTextNode)
{
var as=document.getElementsByTagName('a');
var j = 0;
for (var i=0;i<as.length;i++)
{
if(as[i].rev == 'popphoto') {
ary = img_array[j];
as[i].onclick=function(){show_pop(this, ary);return false;};
j++;
}
}
}
}


(Via the show_pop script, this allows the user to click on a photo thumbnail in a gallery and the enlarged photo "pops up" in a layer. [getElementsByTagName is a function defined in a separate file.])

The problem is that "ary" is passed by a reference. So when the script stops running, each of the thumbnail anchors has the value of the last one, not its own individual value.

(I tried the same thing just passing the "j" variable, and all anchors ended up with the final value of "j".)

Is there any way to force this to pass "j" or "ary" by its value, rather than its reference, so that subsequent iterations only apply to their intended objects and not the ones already processed?

I'm going mad here ...

For your reference, here's the value of "img_array":

var img_array = new Array();
img_array.push(new Array(0,"images/Images/5b185be7.jpg",640,480,"One-Act Play 1, The Auditioners"));
img_array.push(new Array(1,"images/Images/9843002c.jpg",640,427,"One-Act Play 2, The Auditioners"));
img_array.push(new Array(2,"images/Images/772965a.jpg",640,427,"One-Act Play 3, The Auditioners"));
img_array.push(new Array(3,"images/Images/e6e4f9a2.jpg",640,427,"One-Act Play 4, The Auditioners"));
img_array.push(new Array(4,"images/Images/58a2081a.jpg",640,427,"One-Act Play 5, The Auditioners"));


A simplified version of "show_pop" to demonstrate:

function show_pop(l, ary) {
var id=l.href
alert('i: ' + ary[0]);
}

No matter which thumbnail I click on, the value of ary[0] is 4 (the final value). By contrast, the value of "id" is the correct one for each object.

oacis
03-03-2010, 01:22 PM
oheso --

You can read about the problem you are having with JavaScript closures at these two links...

[ http://james.padolsey.com/javascript/closures-in-javascript/ ]
[ http://stackoverflow.com/questions/341723/event-handlers-inside-a-javascript-loop-need-a-closure ]

Try changing

as[i].onclick=function(){show_pop(this, ary);return false;};

to


as[i].onclick = (function(that, handler_ary)
{
return function()
{
show_pop(that, handler_ary);
return false;
}
})(this, ary);


Executing the function assigned to the click handler immediately will form a closure (the inner function) that maintains the value of ary that was current for each pass through the loop

-- Wayne

oheso
03-03-2010, 08:19 PM
Wayne, thanks for the pointers and code! I'll give it a shot.

oheso
03-04-2010, 02:14 AM
That works! All I needed was a little closure ... Thank you again!

michael123
04-17-2010, 05:11 AM
Hi Oheso,
I also used it and The problem is that "ary" is passed by a reference. So when the script stops running, each of the thumbnail anchors has the value of the last one, not its own individual value.how can i solve it Oheso?

oheso
04-18-2010, 02:58 AM
Michael, you're having the problem that I was originally having. Working from the links and code from Wayne (oacis), I came up with this:


function image_pops_init()
{
if(document.getElementById && document.createTextNode)
{
var as=document.getElementsByTagName('a');
var j = 0;
for (var i=0;i<as.length;i++)
{
if(as[i].rev == 'popphoto') {
as[i].name = img_array[j].join('#');
/* as[i].onclick=function(){show_pop(this);return false;}; */
as[i].onclick = (function(handler_array) {
return function() {
show_pop(handler_array);
return false;
}
}) (img_array[j]);
j++;
}
}

}
}


You can see where I've made the change after the line I commented out.

Give it a try. If you have any problems, give a shout again.