views:

394

answers:

4

So I have a class foo that has a method which returns an array bar. I have another function that calls foo.getBar and then filters the array. I want to be able to always get the original contents of bar when I use a different filter, but bing seems to be just creating a reference to bar, not a separate array. I have tried using return this.bar.valueOf(); in my function foo, still not working. When I remove items from bing they are also removed from bar. Someone please enlighten me on creating a unique array instead of a reference.

function foo(x, y, z){

    this.bar = new Array();
    ...
    this.bar = [ some , stuff , in , bar ];

    this.getBar = function getBar(){
     return this.bar; 
    }
    ...
}

var FooObject = new foo(x,y,z);

function baz(){

    var bing = FooObject.getBar();

    bing.splice(remove some pieces of the array);
}
A: 

What you'll have to do is something like the following, passing a function as a parameter and force a pass-by-value;

function foo(x, y, z) {
    this.bar = ['uno', 'dos', 'tres'];
}
foo.prototype.getBar = function() {
    return this.bar;
}
...
function getBar(fn) {
    return fn();
}
...
var f = new foo(x, y, z);
var bing = getBar(f.getBar);
Björn
A: 

Returning a "clone" will make sure original array is untouched. Note that such clone will be shallow.

function foo(x, y, z){

    this.bar = [ some , stuff , in , bar ];
    ...
    this.getBar = function getBar(){
       return this.bar.concat([]);
    }
    ...
}
kangax
A: 

Unfortunately javascript arrays and objects are always passed by reference. If you are guaranteed that your foo.bar array is 1-dimensional/contains no arrays or objects,

Then you can do:

var bing = FooObject.getBar().slice(0);

Which will do a 1-deep copy of foo.bar, resulting in your bing array being independent of the foo.bar array.

Otherwise you'll have to roll/find a deep copy method, such as the $A function in mootools

var newArray = $A(oldArray)
Johrn
+3  A: 

The easiest (and as far as I know, fastest) way to get a copy of an array is to use the slice method. Without any arguments, it defaults to array.slice(0, array.length), so it will copy the entire array.

Your getBar function would look like this:

this.getBar = function getBar(){
    return this.bar.slice();        
}

Note that this is a shallow copy, so any changes to the objects in the array will affect the original (adding and removing items won't affect it though).

Matthew Crumley
My array contains objects, but the objects themselves won't be changed, they just need the ability to be added again.For example [ Object Ford , Object Chevy , Object Toyota , Object BMW ] I might run baz to display only American cars, so I want to be able to remove Toyota and BMW from the array, then run a method on the remaining objects to render some HTML, but if the filter is removed I want to be able to run the render HTML method on all the array items again. The objects themselves won't be changed, just removed from the copy of the array. Will this work then?
Jesse
This seems to work thanks everyone for the prompt responses! This is my first time posting on Stack Overflow and it certainly won't be my last.
Jesse
Yes, that will work.
Matthew Crumley