JSON.parse(json_string_from_php) produces weird array - javascript

I'm having a bit of difficulty with transferring a JSON object from the server to the client-side javascript
I have a rows of data fetched from MySQL query stored into $result
Here's the code:
var json = '<?= json_encode($result->fetch_all()) ?>';
var word_list = JSON.parse(json);
console.log(word_list); //index.php:23
console.log(json); //index.php:24
This is the result in chrome console:
Can someone tell me:
1. Why line 23 shows length of 5 when folded, then only show length of 4 when unfolded?
2. Where did word5 go? FYI, the word that disappears changes every time I refresh.

I am able to reproduce your screenshot.
I purposely hovered over the little "i" to reveal its tooltip. It states "Object state below is captured upon first expansion.
This means that if you print the array, don't expand it, modify the array (say with a pop()) then when you expand it you will see the modified array.
Demo: JSBin

console.log logs your state of the object to the console when it is hitting the console.log while inspecting the array (or any object) shows you the current state of it.
var a = [1,2,3,4,5].map(function(){ return new String(); });
console.log(a);
a.pop();

Related

Why does this array have object key value pairs?

I didn't even know that this was possible, what is this? I tried running this on chrome and firefox, and got the same result:
I'm sending a 100 item array from the server, but when it gets to the client, this happens.
I tried accessing the item at index 100, and got undefined as response.
I also tried slicing it to the first 100 items, but the rest of the key pairs remain there.
I can't try to access the values by key because they are random every time. If that's of any value.
Since an array is also an object, you can add arbitrary properties to it. Run this code then look in your browser console (not the console inside this post).
const array = ['11034.61000000', '0.30200000'];
array['10987'] = 0.009101;
array['11024.05'] = 0.001998;
array['11026.96'] = 0.001;
array['11026.59'] = 1.5;
console.log(array);
console.log(Object.keys(array));
Object.keys(array) will show you every property of the array, even the random ones.

Javascript: JSON key values not updating on request

I'd like to update my JSON value based on selection.
So for that I have simply update my json value as data.childShow = true.
Now as per the screenshot on line no 78 it's actual value is false and after updating it's value to true ( ref line no 84 ) and it shows as value updated on line no 85 but when i expand that console object it shows as false.
So, why the values are differing when open the object on console log ?
Screenshot while not opening object of line no 85
P.S: Before raising this question I have already tried this demo, but it is not working in my actual application so that i raised this question.
Try this thing in console it might solve your confusion. Add an object like let data = { childShow: false }. Then log it in console. Do not expand right now. Now change the value of data.x = true; in expanded value but it also has childShow=false in first line. Now expand console log value. You can see it is displaying childShow = true. So it might be fetching current values when we expand.
You can also log childShow and check what exactly values hold by data.childShow. Like in below snippet. It will show you when you do console.log(data.childShow); first time it will show false and second time it will show true which is as expected.
Try with below like. 1. Open console of browser. 2. Click on Run Code Snippet. 3. Expand object in console.
const data = {
childShow: false,
}
console.log(data);
console.log(data.childShow); // Output false
data.childShow = true;
console.log(data);
console.log(data.childShow); // Output true

Parsing a JSON object of arrays gives different results in IE9

Intro
I am working on creating a HighCharts graph from a DataTable table.
What I do is iterate over the the rows and columns of the table, convert the strings (we use different thousand separators from the US) to numbers and save them into an object called item. the object has two values item["name"] which is the name of the series and item["data"] which is the data for the series. I then use the .push method to add these objects to an array to send to a Highcharts options object to create the plot. In the case below, I only have three series, but the problem always occurs. The LineOptions is an options-object for the HighCharts Graph.
Code
function plotLineOrBar(type){
var jsonData = [];
var xaxis = $('#masters_table table').find('thead th:not(:first-child)').map(function(){
return $(this).html();
}).get();
$('#masters_table table tbody tr').each(function(){
item = {};
item["name"] = $(this).find('td:first-child').html();
item["data"] = $(this).find('td:not(:first-child)').map(function(){
return parseInt($(this).html().replace(/\./g, "").replace('',0),10);
}).get();
jsonData.push(item);
});
console.log(jsonData[0]["name"]); // send the 0th name to console
console.log(jsonData[1]["name"]); // send the 1st name to console
console.log(jsonData[2]["name"]); // send the 2nd name to console
LineOptions.series = (jsonData);
LineOptions.xAxis.categories = xaxis;
LineOptions.chart.type=type;
var chart = new Highcharts.Chart(LineOptions);
}
Problem
(The name of the series should be 2320,2321,2336)
In Chrome, the resulting console.log is:
2320
2321
2336
and the corresponding data to each series prints out correctly and everything works flawlessly.
In IE9, the resulting console.log is:
LOG: 2336
LOG: 2336
LOG: 2336
i.e., only the last series gets printed into the array. The result is three series with perfectly overlapping curves, since they have the same data.
I have searched and searched for answers, wrapped by brain around but I can still not figure out what I am doing wrong. I assume though, that my error is a simple one (I hope).
As previously wrote in the comment (for future reference), just define the item variable inside of the loop function, instead of using a "global" one (var item = {} instead of item = {}). This is because in IE9 it seems to be passed by reference, and thus you're pushing the very same object, updated three times (changing its values from iteration to iteration).
P.S.
by the way it seems that the other browser you're using, it is creating a new variable every time you use .push and I'm not sure that's the "standard" behavior. One point to IE9!

Incorporating localStorage in a more complicated scenario (save multiple arrays)

I'm trying to implement local storage into my program.
Initially, the program was simple and had only 1 array to save. That array served as the container and the container then fed to #1 - the display output and to #2 - the console output...
old simpler program
pseudo-code to make the red box go away...
The above link eventually worked - as you can see on line 54 of the JS, as soon as a new entry is entered into the input box, the updated container was then saved to localStorage. And then upon returning to the site, per line 11 - if upon the initial loading of the program the saved localStorage container doesn't match the initial array, then the saved container is used.
However, I've changed the program drastically so that there are now multiple options to choose from and thus multiple arrays. Whichever option/array is chosen becomes the main container, and the main container still feeds out to the display output and the console output. See the updated program below...
multiple arrays = more complicated program
pseudo-code
The problem is that I am now having a difficult time figuring out how to implement localStorage on this new updated program. It was much easier previously when I only had 1 array to test against. Now, I can't just save the container any time a new entry is inputted (or removed) because the container can be any 1 of the 6 options.
Does anyone have any general ideas/pointers/suggestions as to what I can do?
The easiest (maybe not the most efficient) option would be to use an array of arrays. If before you had:
var container = ["a", "b", "c"];
localStorage.setItem("container", JSON.stringify(container));
You'd now have:
var container = [
["a", "b", "c"],
["d", "e", "f"]
];
localStorage.setItem("container", JSON.stringify(container));
Then for getting a single one in your new code, you'd just do:
var container = JSON.parse(localStorage.getItem('container')); //The same as before
var firstItem = container[0];
Hope this helps. Cheers
Why not just create a JSON object with multiple arrays, and save the entire stringified object in a localStorage variable instead of that single-dimensional array. It could even have a parameter referencing the selected container, and could be structured something like:
var containers = {
selectedContainer: "container1",
container1: ["text","contents","of","container1"],
container2: ["text","contents","of","container2"],
container3: ["text","contents","of","container3"],
container4: ["text","contents","of","container4"],
container5: ["text","contents","of","container5"],
container6: ["text","contents","of","container6"]
}
Content could then be pushed and popped to each of these container arrays, and the entire object saved in the single localStorage variable:
containers.container1.push("additional contents");
localStorage['containers'] = JSON.stringify(containers);
obj = JSON.parse(localStorage['containers']);
You could then reference the selected array with the selectedContainer parameter:
var container = (obj[obj.selectedContainer])

Changing the variables of a class in OOP in javascript

I have defined a function called Node which stores the properties of nodes in a graph data structure. The function is something like this:
function Node(){
...
this.outEdges = [];
this.inEdges = [];
...
}
where the inEdges and outEdges store elements of type Edge which is another function I have defined. During the program these arrays are filled with elements.
At some point in my code I need to reset these two arrays so I write:
nodes[i].outEdges.length = 0;
nodes[i].inEdges.length = 0;
where nodes is an array of elements of type Node and I am accessing an element in a for loop.
The problem is, after setting outEdges and inEdges to 0, I expected them to be [] in the nodes[i] property list. However, when I output nodes[i] into console, the outEdges and inEdges still have the elements in them. The stranger thing is that when I output nodes[i].outEdges to console, it prints [] , which is correct, but clicking on [ ] again opens the list of the elements! I can't really figure out why the nodes[i] variables don't change?
That happens (probably) because the browser prints out the empty array but by the time you check it, it has content again. So when you click to expand the browser shows the actual content.
As you can see the values [1,3,7] were added after the command console.log(o) but they are shown on the screen (even though the length shown is 0).
You're not supposed to set the length field. Just re-initialize them:
nodes[i].outEdges = [];
nodes[i].inEdges = [];
Edit: My bad, setting the length should work. It does work for me on Chrome at least. However, I still think it's safer and better style to re-init.
Just create a new object with the same name
nodes[i].outEdges = new Array();

Categories