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

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));

Related

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.

Push JS Object to array overwrites existing objects [duplicate]

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 :-)

Loop is adding too many items to the final array [duplicate]

This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 4 years ago.
When i use Array.fill to fill a multidimensional array, i get a weird behaviour when pushing to one of the arrays:
var arr = Array(2).fill([]);
arr[0].push(5);
console.log(arr);
//=> prints [[5], [5]]
fill is essentially doing this:
var content = [];
for (var i = 0; i < 2; i += 1) {
arr[i] = content;
}
So, your array will have a reference to the array you've passed to fill in each property.
It sounds weird, but what your code actually does is create an array ([]) and put a reference for that array in each of the items of the Array(2). So whenever you change that reference - every array that is referenced to that Array is changed.
It's exactly the same as:
var a = [];
var arr = Array(2).fill(a);
a.push(5);
console.log(arr[0][0], arr[1][0]);
a[0] = 2;
console.log(arr[0][0], arr[1][0]);
You can see that the values inside the arr are affected by the change to the a array.

Why is array = Array(10).fill(Array(20).fill(-1)) not the same as array [[-1,..,-1], ..., [-1,..,-1]]? [duplicate]

This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 4 years ago.
I tried to create a 2-dimensional array in javascript. (Actually, the code is written in typescript and will be used to style DOM Elements with Angular2 but, as far as I am concerned, it shouldn't have any effect on the result in this case.)
First way:
arrayi = Array(10).fill(Array(20).fill(-1))
Second way:
array = [];
for(var i: number = 0; i < 10; i++) {
array[i] = [];
for(var j: number = 0; j< 20; j++) {
array[i][j] = -1;
}
}
If I call array[1][2] = 2; it does what I expected, what means setting one element in the 2-dimensional array to 2.
However, if I call arrayi[1][2] = 2; every element arrayi[x][2] will be set to 2. (With x element {0,1,2,...,9})
Why is that? I don't understand it. So it would be nice if someone could explain it to me.
The arrays are defined as array: number[][] and arrayi: number[][] in typescript.
arrayi = Array(10).fill(Array(20).fill(-1)) fills with the same array.
You can even rewrite it like this
const arr1 = Array(20).fill(-1)
const arrayi = Array(10).fill(arr1)
console.log(arrayi.every(item => item === arr1)) //true
The reason is that you create one instance of array with 20 elements and put this single instance into each element of root array

O/P of Javascript code [duplicate]

This question already has answers here:
Javascript Object returns junk values
(2 answers)
Closed 8 years ago.
In the below JavaScript code :-
var a = [];
for (i in a) {
alert(i);
}
I am getting o/p as - $family, $constuctor, each, clone, clean, invoke, associate, link, contains, append, getlast, getRandom, include, combine, erase, empty, flatten, pick, hexToRgb, rgbToHex.
Can anybody explain why is that so?Has it got to do something with properties of Array objects and if so then why aren't all the properties alerted? Also , if we take a empty object literal like var a = {} , we don't get any o/p.
Now , if I change the above code like :-
var a = [9,2];
for (i in a) {
if (a.hasOwnProperty(i)) {
alert(a.hasOwnProperty(i));
alert(i);
}
}
I get the output as 0 and 1.Why is that so ? Are those the properties of this Array object (which are also the indexes) ?
The for-in syntax is for objects. It iterates all fields of the object, including methods. When you want to iterate an array, always use this:
for (var i = 0; i < array.size; i++) {
doSomething(array[i]);
}
Your latter loop with hasOwnProperty doesn't iterate over the standard methods of arrays, because your array a inherited these methods from the base Array class, so they aren't it's own properties. But when you explicitely add a method to an array, it should also list the function because it is now an own property:
var a = [9,2];
a.hello = function() { };
for (i in a) {
if (a.hasOwnProperty(i)) {
alert(a.hasOwnProperty(i));
alert(i);
}
}
This should list 0, 1 and hello.
In case you expected it to output 9 and 2 and you wonder why it outputs 0 and 1: That's because the for-in array iterates over the keys, not over the values. And arrays are basically objects where each array element is a property with the array index as a name. So
var a = [9, 2];
is equivalent to this object (plus the stuff inherited from Array):
var a = {
0: 9,
1: 2
}

Categories