I have some code:
var cart = [];
var items = [];
var cart_node = document.querySelectorAll('#tblItineraryModuleStayDetail > tbody > tr');
var cart_as_array = Array.prototype.slice.call(cart_node, 2); // start at item 3 (2)
for(var i=0;i<cart_as_array.length;i+=2) {
items.push(cart_as_array[i]);
}
Now, in the console if I type items I get:
So I expect the loop to go around once in this instance.
Here's my loop:
for(i=0; i < items.length; i++) {
// set vars
cart[i] = {};
var name = items[i].querySelector('.txtStayRoomDescription').textContent;
var price = items[i].querySelector('.tblItinPriceSummary tr td:last-child').textContent;
var brand = items[i].querySelector('.txtStayRoomLocation').textContent;
// add to object
cart[i].name = name;
cart[i].price = price;
cart[i].brand = brand;
// add to cart array
cart.push(cart[i]);
}
Which gives:
I expected a result with array cart containing one item object not two. But it has two identical objects.
What's going on here?
You're first setting the ith element of the cart array as your object, then also pushing it onto the end; this will put two copies in, as you see.
Edit for question in comments:
Let's go through your code line by line:
for(i=0; i < items.length; i++) {
// set vars
cart[i] = {};
After cart[i] = {} puts an empty object in the cart array at index i; if there was something there before, it will be overwritten, otherwise the array will simply be added.
// stuff setting properties removed
// add to object
cart[i].name = name;
cart[i].price = price;
cart[i].brand = brand;
Now, the object at cart[i] has received the attributes you constructed. The cart array now contains an object with these name, price, and brand attributes at position i.
// add to cart array
cart.push(cart[i]);
Now, in addition to the reference at i, you've pushed a second reference to the object stored at i on to the end of the array. This will produce the behavior you are observing: the object will be in the array twice.
I would recommend changing cart[i] = {} (and the associated code that adds properties of this object) to construct the object while it is stored in a local variable, then push it on to the array at the end of the loop.
At line 3 of your code you create an empty object in your array:
cart[i] = {};
then at line 14 you push that object into your array again:
cart.push(cart[i]);
You should instead just create an object, and push it at the end:
var item = {};
// ... add properties to item ...
cart.push(item)
Related
I am writing a for loop that is iterating over an array which contains different lines in a text document.
Each iteration I am trying to pull certain parts of each of the text data lines and add them to an object, namely localinoData.
At the end of each iteration I am trying to add the localinoData object (with each object property set to a new one) to a new array.
When just adding the string found in each line the to data array (localinoDataObjArray) I get different values for each of the array. However when I now change the localinoData object properties on each iterations and try to append that changed object to the array, i get the same object in all of the array positions, e.g when I
alert(localinoDataObjArray[x].X_COORD);
for all values of x, the X_COORD is the same.
function GetlocalinoDataFromFile(localinoDataFile){
var localinoDataObjArray = new Array();
var localinoData = {
time: null,
tagID: null,
X_COORD: null,
Y_COORD: null,
Z_COORD: null,
};
var allData = localinoDataFile.responseText;
var arrayOfDataLines = allData.split('\n');
// for each iteration, get the tagID, and the co-ords(seperate) and then
// create a localinoData object and add to array
for (var i = 0; i < arrayOfDataLines.length; i++) {
if (/tag: [0-9]{22}/.test(arrayOfDataLines[i])) {
var tagID = /tag: [0-9]{22}/.exec(arrayOfDataLines[i]);
localinoData.tagID = tagID;
}
if (/[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.test(arrayOfDataLines[i])) {
XYZ_COORDS = /[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.exec(arrayOfDataLines[i]);
temp = XYZ_COORDS.toString();
temp2 = temp.split(', ');
// Here I am changing the object to new values each loop
localinoData.X_COORD = temp2[0];
localinoData.Y_COORD = temp2[1];
localinoData.Z_COORD = temp2[2];
}
// Here I am appending the newly changed object to my array
// however the same object is being added every time
// (which corresponds to the last line in the text document)
localinoDataObjArray.push(localinoData);
}
// the object values for localinoDataObjArray[0]
// and localinoDataObjArray[50] are the exact same
alert(localinoDataObjArray[20].X_COORD);
}
I expect all of the array values to be different corresponding to the different lines in the text document. However all of the array values are the same (which equal the expected result of iteration over the last line in the text document).
I am very confused as when i = 0, it should be adding an object that has the values of the first line in my text document, however it shows the values i would expect from the last line in the document.
This is very strange to me and seems like a looping problem? I am very confused and would appreciate any help in this matter.
They are all references to the same object which you keep overwriting.
Try and make a fresh instance of localinoData in every iteration of your for loop.
function GetlocalinoDataFromFile(localinoDataFile){
var localinoDataObjArray = new Array();
var allData = localinoDataFile.responseText;
var arrayOfDataLines = allData.split('\n');
// alert(arrayOfDataLines[4]);
// for each iteration, get the tagID, and the co-ords(seperate) and then create a localinoData object and add to array
for (var i = 0; i < arrayOfDataLines.length; i++) {
var localinoData = {
time: null,
tagID: null,
X_COORD: null,
Y_COORD: null,
Z_COORD: null,
};
if (/tag: [0-9]{22}/.test(arrayOfDataLines[i])) {
var tagID = /tag: [0-9]{22}/.exec(arrayOfDataLines[i]);
localinoData.tagID = tagID;
}
if (/[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.test(arrayOfDataLines[i])) {
XYZ_COORDS = /[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.exec(arrayOfDataLines[i]);
temp = XYZ_COORDS.toString();
temp2 = temp.split(', ');
localinoData.X_COORD = temp2[0];
localinoData.Y_COORD = temp2[1];
localinoData.Z_COORD = temp2[2];
}
localinoDataObjArray.push(localinoData);
}
alert(localinoDataObjArray[20].X_COORD);
}
Currently, I have an empty new object and I want to populate values from an existing object to new object because I want to use an object with only limited properties from the existing object (e.g. I only want the four properties instead of eight).
Here's how I am doing the mapping so far:
const newObject: any = {};
for (let i = 0; i < this.PRODUCT_DATA.length; i++) {
newObject._productSkuKey = this.PRODUCT_DATA[i]._productSkuKey;
newObject._storeKey = this.itemPriceForm.get('location').value;
newObject._price = this.PRODUCT_DATA[i]._price;
newObject._status = this.PRODUCT_DATA[i]._isActive;
this.updatedProducts.push(newObject);
}
So far, it looks to be storing the values from the existing object to newObject. However, it is only saving the last object values and not the different values from the object. How can I fix this to save all values (not just the last values for every object in the array)?
You need to make a copy of that before pushing in array
const newObject: any = {};
for (let i = 0; i < this.PRODUCT_DATA.length; i++) {
newObject._productSkuKey = this.PRODUCT_DATA[i]._productSkuKey;
newObject._storeKey = this.itemPriceForm.get('location').value;
newObject._price = this.PRODUCT_DATA[i]._price;
newObject._status = this.PRODUCT_DATA[i]._isActive;
this.updatedProducts.push(Object.assign({}, newObject));
// Or
// this.updatedProducts.push({ ...newObjec });
}
Or Simply create object inside loop. I love to use Array.prototype.forEach and Array.prototype.map
this.updatedProducts = this.PRODUCT_DATA.map(({_productSkuKey, _price, _isActive})=> ({
_productSkuKey,
_storeKey: this.itemPriceForm.get('location').value,
_price,
_status: _isActive
});
Avoid declaring newObject as 'const'. This is an updated code that works for me.
//avoid using a const, as you cannot override it
let newObject: any = {};
for (let i = 0; i < this.PRODUCT_DATA.length; i++) {
newObject._productSkuKey = this.PRODUCT_DATA[i]._productSkuKey;
newObject._storeKey = this.itemPriceForm.get('location').value;
newObject._price = this.PRODUCT_DATA[i]._price;
newObject._status = this.PRODUCT_DATA[i]._isActive;
this.updatedProducts.push(newObject);
//after pushing the object, empty all the current contents
newObject={};
}
I have to iterate through an array, change one of its values, and create another array refelecting the changes.
this is what I have so far:
JS:
var arr = new Array();
arr['t1'] = "sdfsdf";
arr['t2'] = "sdfsdf";
arr['t3'] = "sdfsdf";
arr['t4'] = "sdfsdf";
arr['t5'] = "sdfsdf";
var last = new Array();
for (var i = 0; i <= 5; i++) {
arr['t2'] = i;
last.push(arr);
}
console.log(last);
Unfortunately, these are my results
As you can see, I am not getting the results needed as 0,1,2.. instead I am getting 2, 2, 2..
This is what i would like my results to be:
How can I fix this?
You have to make a copy, otherwise you are dealing with reference to the same object all the time. As it was said before - javascript does not have associate arrays, only objects with properties.
var arr = {}; // empty object
arr['t1'] = "sdfsdf";
arr['t2'] = "sdfsdf";
arr['t3'] = "sdfsdf";
arr['t4'] = "sdfsdf";
arr['t5'] = "sdfsdf";
var last = new Array();
for (var i = 0; i <= 5; i++) {
var copy = JSON.parse(JSON.stringify(arr)); //create a copy, one of the ways
copy['t2'] = i; // set value of its element
last.push(copy); // push copy into last
}
console.log(last);
ps: you can use dot notation arr.t1 instead of arr['t1']
The array access with ['t2'] is not the problem. This is a regular JavaScript feature.
The problem is: You are adding the SAME array to "last" (5 times in code, 3 times in the screenshot).
Every time you set ['t2'] = i, you will change the values in "last" also, because they are actually just references to the same array-instance.
You must create a copy/clone of the array before you add it to "last".
This is what will happen in all languages where arrays are references to objects (Java, C#...). It would work with C++ STL though.
I am using this function to pass every element in an array to use it in an if statement The problem is that the function is always returning the last value of the array Please help.
function getQtyCheck()
{
var qty;
var id;
var checkQty = new Array()
if(localStorage.getItem("checkout")!=null || localStorage.getItem("checkout")!=""){
checkQty = JSON.parse(localStorage.getItem("checkout"));
for(var t =0; checkQty.length >t; t++){
id = checkQty[t];
t++;
qty = checkQty[t];
}//end for loop
return {ids:id,qtys:qty}
}//end checkout
}
Then in another part of the script I ma using these variables like this
var result = getQtyCheck();
var id = result.ids;
var qty = result.qtys;
if(this.id == id){
var tqty = this.quantity-qty;
Each loop iteration, you assign id and qty to the currently iterated item. Once the loop is over, you return an object with the LAST iterated item set to your variables. Since your return is immediately after the loop and using variables set within the loop, you will always get the last values.
I think I'm following what you are trying to do now. You want to return every element in the array as an array of objects right?
function getQtyCheck() {
var qty,
id,
checkQty = [],
returnValues = [];
if(localStorage.getItem("checkout")!=null && localStorage.getItem("checkout")!=""){
checkQty = JSON.parse(localStorage.getItem("checkout"));
for(var t =0, len = checkQty.length; len > t; t++){
id = checkQty[t];
t++;
qty = checkQty[t];
returnValues.push({ id: id, qty: qty });
}
return returnValues;
}
}
In the loop, build an array of the objects you want to return. After the loop, return the newly created array.
It's returning the last one every time because you're looping it which is adding it up, but then you're using return outside the loop, which is just going to get the last one that it ran.
You shouldn't return inside the for loop because it will try to return multiple times. What you can do though is push it to an array and then get it at the end.
I'm trying to load up an array of objects that is an array itself, so to speak. So I have an array of names(members) then I'm making a master list that will have name, bugs, enhance, etc. in one row for every name. So I run a simple for loop to load master list but it is telling me that for (0) i, masterList[i].name cannot be loaded because it is undefined. Is there a way around this? Thanks
var mem = getMembers();//get a array of members
var memlen = mem.length;
var masterList = [memlen]; //set to number of members
for(i=0; i < memlen; i++){
masterList[i].name = mem[i]; //set .name to the members list name at i
masterList[i].bugs = 0;
masterList[i].enhance = 0;
masterList[i].epic = 0;
masterList[i].dev = 0;
masterList[i].high = 0;
}
To create your array with a predefined size, use this :
masterList = new Array(memlen);
(with masterList = [memlen] you were just creating an array whose first item is memlen. This wasn't so problematic because the array was automatically growing in the loop but that wasn't your intent)
After that, you need to create each masterList[i] :
var masterList = new Array(memlen);
for (var i=0; i < memlen; i++){
masterList[i] = {};
masterList[i].name = mem[i]; //set .name to the members list name at i
If you don't do it, it's undefined, hence the error you have.
I also added var in the loop declaration to avoid the accidental erasing of another variable named i.
A correct version would be:
var mem = getMembers();//get a array of members
var memlen = mem.length;
var masterList = []; //set to number of members
for(var i=0; i < memlen; i++){
masterList[i] = {
name: mem[i], //set .name to the members list name at i
bugs: 0,
enhance: 0,
epic: 0,
dev: 0,
high: 0
};
}
var x = [7]; does not create a 7-element array. it creates a single element array, index 0, with value 7. You need to do var x = array(7) instead, plus initialize each of those elements to be an object instead, within your loop.
This doesn't set a length. It just creates a new Array with a single member set to the length.
var masterList = [memlen]; //set to number of members
Since you seem to already have an Array, you can use .map to build a new one.
var mem = getMembers();
var masterList = mem.map(function(item) {
return {
name: item.name, bugs: 0, enhance: 0, epic: 0, dev: 0, high: 0
};
});