Javascript Nested Objects/Arrays Code Reduction Problem - javascript

I have an object for a collection of video data called "CollectionData". It has 3 key/value pairs:
collectionData.title - a simple string value
collectionData.seriesData - an array
collectionData.progressData - an array
Each of the 2 array values are objects:
collectionData.seriesData[x].title
collectionData.seriesData[x].year
collectionData.seriesData[x].length
collectionData.seriesData[x].synopsis
collectionData.progressData[x].currentTime
collectionData.progressData[x].progress
To save from having to type out collectionData.seriesData[x] or collectionData.progressData[x] every time to access the key's values I use a "pointer" into the object:
var p = collectionData.progressData[x];
I can then access the values of the keys by using p.currentTime, etc.
This works well if I want to replace a single key's value, i.e. p.currentTime = 25. However, if I want to replace the entire object's value, i.e. p = {currentTime:25,progress=10} the assignment operator does not evaluate the value of the variable p as a pointer into the object but as the pointer itself, therefore the object's value is not updated.
Is there a way to force the assignment operator to evaluate the variable p as a pointer or will I have to revert back to the full object name collectionData.progressData[x]={currentTime:25,progress=10}?

You could take Object.assign and the new data which update the object.
const
data = [{ currentTime: 1, progress: 1 }],
p = data[0];
Object.assign(p, { currentTime: 25, progress: 10 });
console.log(data);

Related

Variable changes type when added to an array

I'm parsing a string to a float, and when I print the type of the variable, I get number. However, if I add the variable to an array, and print it from there, I get string. But if I then index clicks[0], I once again get number
let clicks = []
let latitude = parseFloat(stringCoords.substring(11, 28))
clicks.push(latitude)
console.log(typeof(latitude)) -- prints number
for (var object in clicks) {
console.log(typeof(object)) -- prints string
}
console.log(typeof(clicks[0])) -- prints number
The only thing I'm adding to the clicks array is the latitude variable. I'm confused as to why it's changing types. Please let me know.
The for..in loops through the properties of an object which has the type string. And for..of loops through the values of an iterable object, which has the type of whatever you store in it (In your case, a number).
let clicks = []
let latitude = parseFloat("10.33")
clicks.push(latitude)
console.log(typeof(latitude))
for (var object of clicks) {
console.log(typeof(object))
}
console.log(typeof(clicks[0]))
as 'for(... in ...)' you are navigating through an array, 'object' actually produces the index value of that element, not the element of the current array. When you navigate with the 'clicks.forEach(...)' structure, you access the elements of the array. Therefore, you get a "string", so the operation you do with "typeof(...)" is not on the same elements. One of them gives the array index and the other gives the element of the array.

For loop always uses the last value JavaScript - VueJS

as the title describes the problem, I'm using a for loop to extract elements of an array and asign it to a JSON value, it´s something like this:
hotel={ rooms: 2, price: [ 100, 200 ], occupation: [ '1 child', '1 adult' ]
and want to push into an array of JSON
hotels = [ { rooms:1, price: 100, occupation: '1 child' },... ]
so i tried this:
var json = { rooms : 1, price:null, occupation:null }
for (let i=0 ; i < hotel.rooms ; i++){
json.price = hotel.price[i]
json.occupation = hotel.occupation[i]
this.hotels.push(json)
}
but always the array hotels has the last values of the loop and (shows repeated the last value of the iteration), tried using the try {throw i} catch(ii) {...} but doesnt work
The problem is that each element of the array this.hotels is a reference to the same json object - so when it is mutated, anywhere, all those array elements "see" the change. Since you mutate json in each loop iteration, and simply overwrite the same keys, it's inevitable that each element ends up the same.
To fix it, simply push a new "copy" of the object - which will not therefore be affected by mutations of the "master" json object. There are several ways to do this, one being object spread notation:
this.hotels.push({...json});
You could also use Object.assign({}, json) instead of the spread notation. Or keep your code as it was, but move the var json = {...} inside the loop while replacing var with let - to ensure it's a new local variable each time, rather than one global that's continually mutated. Lots of solutions, as I said.
Object are reference types, you need to create a new object each time you push to the hotels array.
There are several ways to fix this two simple ways would be to:
Use object literals in the push method this.hotel.push({ rooms: 1, price: hotel.price[i], occupation: hotel.occupation[i]})
--OR--
Move the variable declaration into your loop var json = { rooms : 1, price:null, occupation:null }

Why can't you access this array with index?

Why does this array have a length property of 0? And as a follow up to that question, why can't you access an item in this array with an index value?
Consider the following:
var box = [];
box['material'] = 'cardboard';
box['size'] = 'small';
box.length; //0
console.log(box);
//[ material: 'cardboard', size: 'small' ]
box[0]; //undefined
However, when I do the following:
var box = [];
box['0'] = true;
box['1'] = 'cardboard';
box['2'] = 'some value';
box.length; //3
box[0];// true
Why does it output the correct length in this case, since '0' is a string and not a number and access the correct item with the 0 index?
In JavaScript, the length of an array is always one more than the largest numeric (integer) property name. Arrays can have properties whose names are not numeric, but they don't count towards the length of the array (and they are ignored in some other important situations).
Object property names are always strings, but strings that are non-negative integer values when interpreted as numbers are special in arrays. Accessing properties with numeric values works because the numbers are first converted to strings; thus box[0] and box['0'] do exactly the same thing.
when setting box['material'] it creates a property called 'material' with value 'cardboard'. this doesn't add a element to the list!
you need to use .push() or asign the index you want.
also, the '0' string is cased to a number, so obj['0'] and obj[0] is the same (not just for 0, this happens for all numbers)
I think you’re confusing objects with arrays. While arrays are indeed objects in javascript, that doesn’t help us here.
What you are trying to instantiate is an associative array with key-value pairs “material”->“cardboard”, “size”->“small”. However, such a datastructure does not exist in javascript. Array must only have integers as indexes, as in
box = [];
box[0] = 'material';
box[1] = 'someValue';
The reason why your code (which only seems to be an associative array)
box = [];
box['0'] = true;
box['1'] = 'cardboard';
works is because of implicit type conversion. Because you’ve declared box to be an array, a string is not valid in this position, so javascript quietly converts it into an integer, so you again get a plain, boring, integer-indexed array as above.
What you can do, though, is create an object with attributes. So you might, for example, state
box = {}; // box is now an object
box.size = 'small'; // box now has an attribute called “size”
// which has the (string) value “'small'”
box.material = 'cardboard';
or at one go using the notation for object literals:
box = {
size: 'small',
material: 'cardboard'
};
This is the closest you can get to associative arrays in javascript. Note that objects do not have a length. If you want to access the number of attributes they have, you have to use Object.keys(box).length. To iterate over the keys, use
for(var key in box){
console.log('value of ' + key + ' is ' + box[key])
}
Note the array-like notation here, but remember: You’re dealing with objects, not arrays, though dealing with them looks similar. Since box is of type object, you will not only get the attributes you have defined yourself, but also any attributes which are defined for every object. To get only the keys you put in there yourself, use
for (var key in box) {
if (box.hasOwnProperty(key)) {
// do stuff
}
}
If you need to add keys, i.e. attributes at runtime, use (for example)
//supposing that box was instantiated as above
var listOfBoxAttributes = ['shape', 'color', 'weight'];
for(var i in listOfBoxAttributes)
box[listOfBoxAttributes[i]] = undefined;

JavaScript Array Issue with data['sax']

I have a confusion of what this array can hold. Also, I want to know how it assigns the values to the variable set.
Can someone give me an example of data['sax'] please and explain me the loop below?
for(var x = 0; x < data['sax'].length; x++){
var set = data['sax'][x];
Then what does this mean ?
id : set.saxID,
name : set.symbol
What you have here is an array that is being looped through. data['sax'] will be something along the lines of the following:
var data = {
sax: [
{
saxID: 1,
symbol: 1
},
{
saxID: 2,
symbol: 2
}
]
}
As you can see in the example above, sax is an array which contains multiple objects. What happens when you loop over it, is that it accesses one of the objects inside the array. So data['sax'][0] will give you the object with saxID: 1.
Using the variable set to temporarily store the data in; you can access the data of data['sax'][0] as set. So data['sax'][0].saxID becomes set.saxID. It is somewhat of a shorthand version of accessing the data.
What happens with id: set.saxID, is that the values get assigned to a new object. Which will be something like the following.
var newSax = {
id: set.saxID
}
You are basically transferring data from one object to another.
Explaining the code
var set = data['sax'][x];
Here you are creating a variable called set and assigning it a value from data['sax'][x].
data['sax'] this might look like a array But Its Not, to access value of a array we use index but here its a string. This is another way of accessig a property value of a object. So data is a object with one of its property being sax. That means
data = {sax: somevalue};
Now we have,
data['sax'][x] So as you know data['sax'] is a object and then this [x] , here x is not a string its a variable and it holds the Number value (0,1,2,3...) , it means your data['sax'] value is a array since we are accessing from index.
So from the above analysis your data['sax'] will be in this format.
Array
data = { sax : ["someValue","someValue"]}
So variable set will be
var set = "someValue"; // if x = 0, as in the first loop
Now coming to the code
id : set.saxID,
name : set.symbol
set.saxID this is used if the set is an object. In Jquery to retrieve the value of a property in the object you use the . operator with property name (or by the property name as seen above). So the code means set is a object with two properties saxID and symbol. So your set object will be like
set = { saxID: 123, symbol = "TEST"}
That also means that your data value be
data = { sax : [{saxID: 123, symbol = "TEST"},{saxID: 123, symbol = "TEST"}]}
Let me know if I was clear

Values of variables with negative and big array indexes does not save in local storage

I have variable with uncommon array indexes. Here it is:
http://i.imgur.com/01nH8x5.png
So, I save it into local storage:
function Save(){
var save = {
//<...>
MapCellData: MapCellData,
MapCellDataE: MapCellDataE
//<...>
};
localStorage.setItem("save",JSON.stringify(save));
}
window.setInterval(function(){
Save()
}, 10000); // Autosave every 10 sec
Then I go to Firebug console and check what elements were saved by entering the following command:
JSON.parse(localStorage.getItem("save"));
This is what I get: http://i.imgur.com/vva3mBk.png
As you see, all values of variable with negative indexes and big indexes became undefined while indexes from 0 to 4 were saved properly.
Note: MapCellData is variable which determines which image will be applied to the table cell, and MapCellDataE is variable which determines cell background colour. Both of these variables have same indexes, so both share the same problem. Variables that does not have so strange indexes saves properly.
This is how it looks visually.
Before I reload a page: http://i.imgur.com/B3FSu5e.png
After I reload a page: http://i.imgur.com/rhkZAa1.png
Yes, JSON.stringify does only serialise array indices1 on Array objects, and discards all other properties. The solution is trivial - don't use arrays when you shouldn't be using them:
var MapCellData = {}; // instead of []
MapCellData[weirdProperty] = …;
This will be much more space-efficient in JSON as well, given how sparse your "array" is.
1: §6.1.7, §9.4.2: An array index is a String-valued property key that is a canonical numeric String and whose numeric value i is in the range +0 ≤ i < 232−1.

Categories

Resources