Stop the changing of one objects param affecting copies of that object - javascript

Say I have multiple arrays.
var array1= [];
var array2= [];
var array3= [];
And I have another array of objects, each with a health parameter.
Say I push the first object in this array into array1, array2 and array3.
Now if I edit the health parameter of array1's object:
array1[0].health -= 50
it changes the health for each arrays object. How can I do it so it only does it for the array im calling into?

If you want a copy of the object in each array, and you don't want the modification of one to affect the others, then you will need to clone the object. The answers on this post will help you with this:
What is the most efficient way to deep clone an object in JavaScript?

Objects in javascript are assigned by reference so if you put the same object into two separate arrays, each array element points at exactly the same object.
If you want separate objects in each array, then you have to explicitly make a new object for the second array (copying properties from the first object if that's what you want).
In jQuery, you can use $.extend() to make a copy of an object. See this answer for two different ways to use it.
Or, in plain Javascript, here's a function that makes a shallow copy of a plain JS object.
function copyObj(src) {
var copy = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
copy[prop] = src[prop];
}
}
return copy;
}

var array1 = []
var array2 = []
array1.health = 50
array2.health = 10
console.log(array1.health)
50
it still remains 50. On the other hand if your question relates to changing array elements as such
var array1= [0,1]
array1[0].health = 50
array1[1].health = 10
console.log(array[0].health) will print out 10 because health is an property of the array object not the element.

Related

Javascript object properties with same values experience the same changes when they shouldn't (splice)

I'm not sure if this is a bug or if I have a complete misunderstanding of Javascript, but this is what happens:
I take an object with two arrays inside it, one representing the current queue of IDs and another representing the total queue of IDs (hypothetical situation)
var mainObject = {
object1:[],
object2:[]
};
In a function, we set the two property arrays to the same variable which holds the array needed before we can start processing the queue.
var randomVar = [1,2,3,4];
mainObject.object1 = randomVar;
mainObject.object2 = randomVar;
Now we want to make use of the splice method to remove the first index from object1 while keeping it on object two.
mainObject.object1.splice(0,1);
The result of the object is now as follows:
mainObject = {
object1:[2,3,4],
object2:[2,3,4]
};
meaning that both of the properties were spliced when we only asked Javascript to run it once.
See JS Fiddle for live example:
https://jsfiddle.net/ypow6y8g/
Is there something I'm missing or is this just another night spent with loose JS?
You have one array, and two variables whose value is a reference to that array. When you modify the value of one of those variables, you modify the other one as it's the same.
If you want your arrays to be independent, clone one:
var randomVar = [1,2,3,4];
mainObject.object1 = randomVar;
mainObject.object2 = randomVar.slice(); // slice returns a new array

How to store number of object element of array in another array?

im trying to store some object element from one array to another so lets say i have this array of objects
var Array = [{name:'Fadi'},{name:'Joseph'},{name:'Salim'},{name:'Tony'}];
and i want to store the first two object in this array to another array so it would like be
var SubArray =[{name:'Fadi'},{name:'Joseph'}];
thanks in advance for any help.
You can use slice method for this:
var SubArray = Array.slice(0,2);
Please note that Array is reserved JS global object. You need to use different name for that variable. So your code should be for example:
var MyArray = [{name:'Fadi'},{name:'Joseph'},{name:'Salim'},{name:'Tony'}];
var SubArray = MyArray.slice(0,2);
If you need conditional logic you want Array.filter(). If you know you always want the items by index then use slice as in antyrat's answer.
var originalArray = [{name:'Fadi'},{name:'Joseph'},{name:'Salim'},{name:'Tony'}];
var subArray = originalArray.filter(function(obj,index) {
return obj.name=="Fadi" || obj.name=="Joseph";
})

Strange array.push in JS

I have simple code
sites_from_session = 12;
function function_name () {
var items_to_send = sites_from_session;
var template_name = jQuery('#new-site-template-name').val();
console.log(sites_from_session);
items_to_send.push(template_name);
console.log(sites_from_session);
}
function_name();
function_name();
function_name();
function_name();
function_name();
function_name();//...
The problem is that the push method pushes value to both arrays
Where i am wrong?
Arrays do not self clone in JavaScript. When you say something like
arr1 = arr2;
where both arr2 is a valid array, you haven't made an actual copy of arr2. All you've done is create a reference pointer to it for arr1. So when you make a change like
arr1[0] = "some value";
you are (in essence) saying the same thing as
arr2[0] = "some value";
To properly clone a separate copy you need to use this:
var items_to_send = sites_from_session.slice();
This will return a new array that holds all of the items from the original array.
It is a very common Javascript problem. The arrays are not copied like this:
var items_to_send = sites_from_session;
It merely copies the reference of the array to a new variable. In other words, items_to_send and sites_from_session are two names pointing to the same array in RAM. If you want to make a copy of the array (called deep copying) rather than just another pointer (shallow copying), you need to use slice():
//create a copy of the array
var items_to_send = sites_from_session.slice(0);
The rest of your code should work fine.
Possible duplication of this question: How do you clone an Array of Objects in Javascript?
You can learn more here: http://davidwalsh.name/javascript-clone-array

Test for value within array of objects

I am dynamically building an array of objects using a process that boils down to something like this:
//Objects Array
var objects = [];
//Object Structure
var object1 = {"id":"foobar_1", "metrics":90};
var object2 = {"id":"some other foobar", "metrics":50};
objects[0] = object1;
objects[1] = object2;
(Let it be said for the record, that if you can think of a better way to dynamically nest data such that I can access it with objects[i].id I am also all ears!)
There's ultimately going to be more logic at play than what's above, but it's just not written yet. Suffice it to say that the "object1" and "object2" parts will actually be in an iterator.
Inside that iterator, I want to check for the presence of an ID before adding another object to the array. If, for example, I already have an object with the ID "foobar_1", instead of pushing a new member to the array, I simply want to increment its "metrics" value.
If I wasn't dealing with an array of objects, I could use inArray to look for "foobar_1" (a jQuery utility). But that won't look into the object's values. The way I see it, I have two options:
Keep a separate simple array of just the IDs. So instead of only relying on the objects array, I simply check inArray (or plain JS equivalent) for a simple "objectIDs" array that is used only for this purpose.
Iterate through my existing data object and compare my "foobar_1" needle to each objects[i].id haystack
I feel that #1 is certainly more efficient, but I can't help wondering if I'm missing a function that would do the job for me. A #3, 4, or 5 option that I've missed! CPU consumption is somewhat important, but I'm also interested in functions that make the code less verbose whether they're more cycle-efficient or not.
I'd suggest switching to an object instead of an array:
var objects = {};
objects["foobar_1"] = {metrics: 90};
objects["some other foobar"] = {metrics: 50};
Then, to add a new object uniquely, you would do this:
function addObject(id, metricsNum) {
if (!(id in objects)) {
objects[id] = {metrics: metricsNum};
}
}
To iterate all the objects, you would do this:
for (var id in objects) {
// process objects[id]
}
This gives you very efficient lookup for whether a given id is already in your list or not. The only thing it doesn't give you that the array gave you before is a specific order of objects because the keys of an object don't have any specific order.
Hmm , i wonder why dont you use dictionary cause that is perfectlly fits your case. so your code will be as below:
//Objects Array
var objects = [];
//Object Structure
var object1 = {"metrics":90};
var object2 = {"metrics":50};
objects["foobar_1"] = object1;
objects["some other foobar"] = object2;
// An example to showing the object existence.
if (!objects["new id"]){
objects["new id"] = {"metrics": 100};
}
else {
objects["new id"].matrics++;
}

JavaScript: How to efficiently replace all values of an object without replacing the object

I have a number of objects collected in an array. The same objects are also attached to certain DOM elements for various reasons. From time to time I need to update one of these objects. The easiest way to do this is to find the object in the array with the same id property as the one I got new values for through AJAX and then replace it. But this of course creates a new object and the objects attached to DOM elements are no longer the same. Which means that if I would compare them they would not be the same object anymore.
How can I easiest replace the correct object with the values in the new object without replacing the actual object? (So that the reference remains the same)
Example of what I don't want
var values = [{id:1, name:'Bob'}, {id:2, name:'Alice'}, {id:3, name:'Charlie'}];
var bar = values[2];
console.info(bar === values[0]); // True
var newValue = {id:1, name:'Dave'};
// Somehow find the index of the object with id==3
values[2] = newValue;
console.info(bar === values[2]); // False, should still be true
Only way I can think of is looping through the object with a foreach or something, but hoping there is something built-in to javascript or jQuery or something that allows for more efficient or at least cleaner code.
You can iterate the values of the new one and set them in the old one:
for (i in newValue) {
oldValue[i] = newValue[i];
}
You could use the handle/body pattern, so the objects in the array only have a single property, which has all the real properties for the object:
var values = [{values:{id:1, name:'Bob'}}, {values:{id:2, name:'Alice'}}, {values:{id:3, name:'Charlie'}}];
var bar = values[2];
console.info(bar === values[0]); // True
var newValue = {id:1, name:'Dave'};
// Somehow find the index of the object with id==3
values[2].values = newValue; // set the values of the object, not the object
console.info(bar === values[2]); // Still true
I'd advise you to replace the objects attached to DOM elements at the same time that you replace the objects in your array. That way, the comparison still holds true.
If that's not possible, then in your example we can see that you only really replace the name property. So you just have to copy the name property from the Ajax object to the Array object.

Categories

Resources