Push JS Object to array overwrites existing objects [duplicate] - javascript

This question already has answers here:
Modifying a copy of a JavaScript object is causing the original object to change
(13 answers)
Closed 1 year ago.
I have this JS object:
baseFarm = {
name: "Farm",
tier: 1,
gridPos: 32,
}
and I want to push it to this array:
ownedLand = [];
This works perfectly, and if I console log this after the push I get:
Now, I want to push another another object to the same array, using that one as a base, however, I want the "gridPos" property to be different:
var newLand = baseFarm;
newLand.gridPos = parseInt( $('#purchaseLandPopupPlotNum').text() );
this.ownedLand.push(newLand);
However, after pushing this new object, the old one gets updated too:
What am I doing wrong?
Thanks in advance

You are assigning the same object to the new variable here:
var newLand = baseFarm;
So when you modify newLand, you are changing baseFarm aswell (and the object pushed to the array). And you are pushing the same object twice to the array.
Instead, you should clone baseFarm, either with Object.assign():
var newLand = Object.assign({}, baseFarm);
Or the more trendy spread operator:
var newLand = { ...baseFarm };
As an addendum, you could clone and modify the property on the same operation:
var newLand = Object.assign({}, baseFarm, { gridPos: parseInt( $('#purchaseLandPopupPlotNum').text() } );
In which case you wouldn't even need a new variable (or the baseFarm even, if it's always on the 0 index of the array):
this.ownedLand.push(Object.assign({}, this.ownedLand[0], { gridPos: parseInt( $('#purchaseLandPopupPlotNum').text() } ));
I'll let the spread version up to you :-)

Related

Existing JSON getting updated if creating a new JSON from the existing one. Why is that happening? [duplicate]

This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 10 days ago.
I have an existing JSON and I take part of the JSON and modify it by creating a new JSON. Now, when I do a console.log of the existing JSON, it shows the existing JSON to have the updates done on the new JSON. Why is that happening ? (I'm doing this in React)
var newJSON = [];
let ifruleObject = oldJSON.rules[0].rules;
console.log(oldJSON);
ifruleObject.forEach((e) => {
for( var i=0; i<ifruleObject.length; i++)
{
if(ifruleObject[i].length <= 3)
{
ifruleObject[i]={ruleid:ifruleObject[i-1].id, rulecombinator: ifruleObject[i]};
newJSON .push(ifruleObject[i]);
}
}
});
console.log(newJSON);
In JS, objects store references. That means, if you assign an object to another variable, any changes made to that other variable will change the original object.
let obj = {a: 10, b: 20};
let copy = obj;
copy.a = 20;
console.log(obj);
console.log(copy);
In your code, you are storing the oldJSON.rules[0].rules object to ifruleObject. ifruleObject now references the original object at oldJSON.rules[0].rules. When you change ifruleObject[i], you are changing the oldJSON object implicitly (see above snippet).
You need to create a new object, copy the elements from the old object, and then assign the new object to your new object. Here is a possible implementation:
let temp = {ruleid: ifruleObject[i-1].id, rulecombinator: {...ifruleObject[i]}};
newJSON.push(temp);

JSON.stringify of an array returns a number after pushing more than one object [duplicate]

This question already has answers here:
Why does Array.prototype.push return the new length instead of something more useful?
(6 answers)
Closed 1 year ago.
I am trying to add products to the cart in my website with localStorage, so I initialize an array and then push products into it. The problem is when I use JSON.parse() to push a product and then stringify it again with JSON.stringify() it returns a number instead of the array. This is the part of my code that throws an error:
let product = {
id: i + 1,
name: productNames[i].innerText,
price: prices[i].innerHTML,
img: imgs[i].src
};
if(localStorage.productsInCart) {
let productsInLocalStorage = JSON.parse(localStorage.getItem("productsInCart") || "[]");
console.log(productsInLocalStorage);
let newArray = productsInLocalStorage.push(product);
console.log(JSON.stringify(newArray));
localStorage.productsInCart = JSON.stringify(newArray);
numberOfProducts.innerHTML = parseInt(numberOfProducts.innerHTML, 10) + 1;
} else {
let productToStore = JSON.stringify([product]);
localStorage.setItem("productsInCart", productToStore);
numberOfProducts.style.display = "block";
numberOfProducts.innerHTML = 1;
};
And then in the console:
enter image description here
That circled 2 is the console.log() of the JSON.stringify. I have been searching for detailed info about this but nothing seems to work.
The trouble is this line:
let newArray = productsInLocalStorage.push(product);
From the MDN Docs: The push() method adds one or more elements to the end of an array and returns the new length of the array. (emphasis mine)
You're assigning the length of the array to newArray.

Using an object clone method and a for loop to push objects into array, the objects are all still the same reference and are the same in the array [duplicate]

This question already has answers here:
What is the most efficient way to deep clone an object in JavaScript?
(67 answers)
Closed 2 years ago.
let promiseArr = [];
for (let i = 0; i < ISOarr.length; i++) {
options.body.start_time = ISOarr[i];
let newOptions = cloneOptions(options);
promiseArr.push(newOptions);
}
console.log(promiseArr);
Returns an array of the same object.
Clone method:
cloneOptions = options => {
let clone = {};
for( let key in options ) {
clone[key] = options[key]
}
return clone;
}
So my question is how do I push an object that is not the same reference as the previous objects pushed, because even with it supposedly creating a new clone each loop it still somehow creates the same referenced object.
In the loop if I console.log I get the proper output with the value of the key changed, but once it's pushed into the array and we console.log the array, all objects are the same. Any suggestions would be super helpful. Thank you in advance!
Can you try this
cloneOptions = options => {
return JSON.parse(JSON.stringify(options))
}

Using reduce() changes order of array [duplicate]

This question already has answers here:
Does JavaScript guarantee object property order?
(13 answers)
Closed 4 years ago.
Within the example script I have generated two arrays I would like to combine to a single row:
var testHeaders = ["aLabel", "bLabel", "cLabel","dLabel","eLabel"];
and
var testValue = ["aValue","bValue", "cValue","dValue","eValue"];
What I am trying to achieve is a string like { aLabel = aValue, bLabel = bValue, ... } that can be used to upload into BigQuery (the data upload job works).
I found a piece of code that almost does this, but somehow it changes the order of the elements within the two arrays.
var code = testValue.reduce(function(obj, value, index) {
obj[testHeaders[index]] = value;
return obj
}, {})
However, the result does mix up the order of the arrays as seen below. I am not capable of figuring out why the order changes. As far as I know, reduce() should work its way from left to right in an array.
The returned object is:
{
aLabel = aValue,
dLabel = dValue,
bLabel = bValue,
eLabel = eValue,
cLabel = cValue
}
You can use map and join:
var testHeaders = ["aLabel", "bLabel", "cLabel","dLabel","eLabel"];
var testValue = ["aValue","bValue", "cValue","dValue","eValue"];
var res = '{' + testHeaders.map((label, i) => `${label}=${testValue[i]}`).join(',') + '}';
console.log(res);
As vlaz pointed out, you are creating neither a string or a new array, but an object. And just like maps, objects do not have a set order of keys in JavaScript. hence, there is quite a chance of getting another order in the object than in both arrays.

trying to copy array of objects by value not reference [duplicate]

This question already has answers here:
What is the most efficient way to deep clone an object in JavaScript?
(67 answers)
Closed 6 years ago.
Hi im aware this subject has been covered in previous posts, but im still not getting the result i need. Im trying to do a copy of an array of objects that that will be its own version of its original, and not affect each others data when changes are made. So far copying an array of ints works fine when i use slice() but not for vector of objects. It was mentioned in another post that slice() on vector of objects will still reference the objects, so is there a way to do it by value only??? Thanks.
property var array: new Array
Rectangle{id: ob1; width:50; height:50; color: "red"; property int num: 1}
Rectangle{id: ob2; width:50; height:50; x: 50; color: "blue"; property int num: 2}
Rectangle{id: ob3; width:50; height:50; x: 100; color: "green"; property int num: 3}
Component.onCompleted: {
array.push(ob1)
array.push(ob2)
array.push(ob3)
var array2 = array //slice() will not work here
array[1].num = 1111 //change made to first array NOT intended for second
for(var i = 0; i < array.length; i++){
console.log(array2[i].num) //print out from second array still shows changes to first...
}
}
You can do something like this:
var copyOfValues = listOfValues.map(function (value) {
return $.extend({}, value);
});
Are you sure array.slice(0) wont work? If not try this:
var array2 = JSON.parse(JSON.stringify(array));

Categories