I want to understand the difference in parameter passing between the three methods used:

- Returning an array in the return statement. (variable a in the code below)
- Returning an array copied as a unit from another array. (variable c in the code below)
- Returning an array, each element individually set. (variable d in the code below)

<html>
<head>
<title>A test</title>

<script type="text/javascript">

function tstarray(x,y,z){
 var i;
 var w = Array(4);
 for(i=0;i<4;i++) {
  w[i] = x[i];
  z[i] = x[i];
 };

 y = z;

 alert('function ' + w + ', ' + x + ', ' + y + ', ' + z);
 return w;
}
 
</script>

</head>

<body>

<script type="text/javascript">

var b = [1,2,3,4];
var a = Array(4);
var c = Array(4);
var d = Array(4);

a = tstarray(b,c,d);

alert('return ' + a + ', ' + b + ', ' + c + ', ' + d);

</script>

</body>
</html>

In both IE and Firefox, the alert in the function returns:

function 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4

But the alert in the calling program returns:

function 1,2,3,4, 1,2,3,4, ,,,, 1,2,3,4

Why is the variable c undefined?

There is an error in my post. The calling program actually returns:

return 1,2,3,4, 1,2,3,4, ,,,, 1,2,3,4

Questions:

1. Can any of you reproduce these results?

2. Does anyone understand why it happens?

the problem you're having is related to references/pointers vs values, which is something JS handles automagically.. ( by passing all non-primitives by reference, similar to Java )

so, when you pass an array into a function, a reference to the array is passed. if you do anything via that array reference ( i.e. change the value of a subscript ) it will be working with the array instanced in the function caller; this is what's happening in the case of 'd' or 'z'.

however, the assignment operator in Javascript (i.e. y = z ) will not affect the referenced array, it will affect the reference itself. There's certainly two different approaches that could be implied by '='. Indeed that's why languages like C++ have values, references, pointers AND operator overloads to clear up any ambiguity.

Think of it like this, in an abstract sense, you have your array, which is made up of a 'handle', an 'array' and some values. They are connected like this:

( we don't see the italics )
[I]handle > [/I] array > *[values]

your calling routine has a handle, when you pass the array to your function, it gets it's own handle to the same array. So in a called routine:

array[n] = 0

means; via my handle, access the nth element of the array, and set it's value to 0. Anything else with a handle to the same array will see the change; so inside, we can imagine it goes something like:

[B]To reference:[/B]
var arrayHandle = new ArrayHandle();
arrayHandle.setArray(array);
[B]To subscript:[/B]
//First dereference:
var tempArray = arrayHandle.dereference();
//Then subscript
tempArray[n] = 0;
//And if we're being this explicit, re-reference:
arrayHandle.setArray(tempArray);

However! if I say:

array = anotherArray

There's an ambiguity over what to assign (array, or handle?). Using the same psuedolanguage, it could go something like:

//Just re-reference the old handle to a new array:
arrayHandle.setArray(anotherArray);

In which case, your calling routine's handle would reference the new array.
It in actual fact, it will appear to do something like this:

//Create a new handle to the new array
arrayHandle = new ArrayHandle();
arrayHandle.setArray(anotherArray);

Hope that makes sense... If you want to have an array that can be altered in this way; you need to create your own 'container' class objects, that'll have methods and work in a way that is quite similar to that anecdotal 'arrayhandle' I've just talked about... in that way, you CAN control the reference to the array, because a caller and a function won't need to overwrite the reference to one of your arrayhandle objects, and the physical reference to the array in that object is then irrelevant to any level below the one you want to be working at.

Thanks. That makes sense.

It also explains how altering the contents of the copy array in the function changed the original array (which I wanted untouched) in the callong program.

So how do I make a real copy of the array that I can change without affecting the original? Do I need to loop through all of the elements and copy them individually?

So how do I make a real copy of the array that I can change without affecting the original? Do I need to loop through all of the elements and copy them individually?

Pretty much; unless Javascript has an Array.copy() function or similar... inbuilt functions might be better optimized, but I doubt it'll make much difference in this case.

.. well, according to this page, one can hijack the Array.slice() method ( which is supposed to return a copy of a segment of an array ) to copy the whole Array.. I really don't know if that would be any more efficient than manual copying, but maybe it's worth a benchmark if you need the speed:

http://www.sematopia.com/?p=12
( Read the comments; the original poster seems to have ommited a neccessary parameter, and someone there explains what happens if you copy arrays of arrays or other arrays of references with .slice(); if you do so, you might want to do it manually, just to retain control )

This article has been dead for over six months. Start a new discussion instead.