reference json numeric key with variable in javascript - javascript

How to loop through this data: (I have no control over format)
{"rowCount":3,"1":{"K":"2009","V":"Some Data"},"2":{"K":"2010","V":"More Data"}}
Above is a console.log(results) and results is a string
var r = JSON.parse(results);
var t;
for(var i=1;i<=r.rowCount;i++) {
t=r[i].V;
tableData.push(
{title:t, year:'2009', hasChild:true, color: '#000'}
);
}
Error: TypeError: 'undefined' is not an object (evaluating 'r[i].V')
I cannot get it to evaluate the variable i. What am I doing wrong?
Thanks
UPDATE
The incoming data had a bad rowcount causing the error. The accepted answer however is correct... just user error on my part not catching the bad incoming data. Had I put a console.log inside the loop I would have realized the error was actually happening after two successful loops. oops

I assume r.rowCount should be j.rowCount.
Ideally you should also initialise the i variable if you haven't already (i.e. with the var keyword).
(I've also moved the var t declaration outside the loop, to make it clear that it's the same t throughout and you're just changing its value. You shouldn't redeclare it with var each time – although I doubt this affects the output.)
var j = {"rowCount":2,"1":{"K":"name","V":"john"},"2":{"K":"name","V":"sue"}};
var t;
for (var i = 1; i <= j.rowCount; i++) {
t = j[i].V;
console.log(t);
}
Working demo – JSFiddle

Related

Javascript Execution not entering for loop

I am facing a really odd problem when executing my JS code. My code execution is not entering a for loop and there are no errors in the console. When I try executing the loop by typing directly in the console, it is executing. Here is the loop :
for(var x = 0; x <= distance; x++) {
var yMinusY1Sq = distance*distance - (x - startX)*(x - startX)
var yMinusy1Cal = parseInt(Math.sqrt(yMinusY1Sq));
console.log(yMinusY1Sq, yMinusy1Cal);
if((yMinusY1Sq == yMinusy1Cal*yMinusy1Cal)) {
y = yMinusY1Cal + startY;
var point = document.createElement("div");
point.className = "output-point";
point.style.height = (grid.offsetHeight/16).toString() + "px";
point.style.width = (grid.offsetWidth/16).toString() + "px";
outputPoints.appendChild(point);
point.style.top = y*oneBoxY;
point.style.left = (x+startX)*oneBoxX;
isodistancePoints.push(point);
}
}
Here, distance is >= 1. The console.log inside the loop is not executing and printing anything. While, if another console.log is put just before the loop, it is printing. So, what is going wrong?
Edit
I tried printing distance, which is a global variable, just before the loop, it is showing undefined, but if it is printed directly using the console, it gives a number value. Here is a screenshot:
Here, is the order of initialization and function, the other global variables initialized are working fine.
var distance;
init();
function init() {
distance = 1;
//Other code
}
$("#run").bind('click', function () {
// some other code
for(var x = 0; x <= distance; x++) {
// some code
}
});
The problem you are facing is in the console. What gets logged is a reference not the value of the object in time. From MDN
Please be warned that if you log objects in
the latest versions of Chrome and Firefox what you get logged on the
console is a reference to the object, which is not necessarily the
'value' of the object at the moment in time you call console.log(),
but it is the value of the object at the moment you open the console.
And the solution is
console.log(JSON.stringify(distance))
or
console.log(`${distance}`)
The problem was that the loop was inside an else statement, and the if of the statement had a local variable named distance. I still don't know the exact cause of the error, as the execution is not supposed to go into the if because its condition is not satisfied, but renaming the variable worked and now I am getting desired output. But if anyone knows the exact reason, please comment.

getting items from LocalStorage gives an error when I try to loop through the items

I'm working on a small project where I try to load some stuff from LocalStorage and append it to my html page.
here's what it looks like:
function fetchList() {
var list = JSON.parse(localStorage.getItem('list'));
var listList = document.getElementById('listList');
for (var i = 0; i < list.length; i++) {
.....stuff
}
I have it set so that I call this function in my body tag
<body onload="fetchList()">
I currently have nothing saved in local storage and it's giving me an error on the FOR loop statement, especially .length. I understand there's nothing there, but wouldn't it just skip to end of loop ?
instead it give sme this error:
Uncaught TypeError: Cannot read property 'Length' of null
Is there a reason why this wouldn't work? What am I doing wrong?
If there's nothing in storage yet, JSON.parse() will return null.
So then var list will also be null.
And null does not have a length property, explaining your error, since a for loop based around the length of something needs that length to be a number.
Try detecting the existance of the JSON string first:
var storedJSON = localStorage.getItem('list');
if ( storedJSON ) {
var list = JSON.parse( storedJSON );
// continue code
}
I think you'll have to check if null first
if (variable == null){
// your code here.
}

In for/while , axios.post send the request with the same body. what the different about axios and $.ajax

When I used axios.post, I met this problem
var len =5;
var a ={};
function abc(temp){
console.log(temp);
axios.post("/",temp);
}
while(len--){
a.name = len;
abc(a);
}
when I run this code in console, it will send 5 time request with the same payload.
The cause is var || let ?
but when I used $.ajax, it works normally.
I wanna an answer, Thanks a lot.
The issue you have is scope of the variable a in the abc function call.
while(len--) {
let length = len;
abc( { name: length } );
}
This creates a new variable length for every iteration and scope is restricted to that iteration.
The answers to this question JavaScript closure inside loops – simple practical example explain in detail about why this happens and about scope and closure in JavaScript. The above question is an exact duplicate of this question.

Loop through object with multidimensional array

I use promises in angular to get some data from the server. In promises success I do
promise.success(function (data, status) {
for (i = 0; i <= data.data.length; i++){
$scope.anArray[i] = data.data[i][1] ;
}
}
I do this because data that came from the server have this structure
{"result":"answered","data":[["jake","508"],["amir","602"],["ben","450"]]}
and I ONLY want to get the numbers 508 , 602 and 450. But I always get the same error TypeError: Cannot read property '0' of undefined reffering to this line : $scope.anArray[i] = data.data[i][0] ;.
Those numbers are feeded to a library to create a chart. Sometimes the chart is created, some times is not. Even if it is created, the same error is always there.
I dont know how to fix that error and getting the chart to be always created without any problems. Looks like the code doesnt like the data.data[i][0] structure, having a simple array like data.data[i] doesnt create an error.
What should I do?
Thanks
Your for loop has an extra execution. You've initialized i to 0 but you've also used <= which means you are going to execute on array[array.length] which is out of bonds. That returns undefined and when you try to access the [0] index on that undefined you get that error.
Change to
for (i = 0; i < data.data.length; i++){
If you're able to do assignment personally I would go with
$scope.anArray = data.data.map(entry => entry[1]);
and skip the for loop entirely. Note if you want to avoid lambdas this would be
$scope.anArray = data.data.map(function(entry) { return entry[1]; });

Keep track of current line number in eval

I'm running some code using eval that will change a $scope object called variables.
Here's my watcher:
$scope.$watch(function () {
return $scope.variables;
}, function (variables) {
console.log('changed!');
}, true);
Here's the code I'm running (this is just example code; it could be any arbitrary code I can't anticipate):
eval('$scope.variables.foo = "bar";\n$scope.variables.bar = "foo";');
In this example, the watcher is triggered twice, and gives me the new values. So far so good. What's missing is the information that the first trigger was caused by the first line in the eval call, and the second one on the second line (note the \n in the eval call denoting a new line number).
Is there a way to achieve this using Angular or just plain JavaScript? I have looked into tools like https://github.com/stacktracejs/stacktrace.js but they don't seem to do the trick.
Just to be clear, I'm not looking for line numbers for when errors are thrown. I need to keep track of which line the eval statement is currently on when the watcher's callback is triggered, so that I can associate that line number with the change that has been made to the object I'm watching.
You could split your input string by \n and insert new statements keeping track of the line numbers
var s = '$scope.variables.foo = "bar";\n$scope.variables.bar = "foo";\n'
var arr = s.split(/\n/);
var out = [];
for (var i = 0; i < arr.length; i++) {
out.push("console.log('current line: " + i + "');");
out.push(arr[i]);
}
out = out.join('\n');
console.log(out);
document.write('<pre>' + out + '</pre>');
You can replace the console.log() by what you want, a call to another function, a debug call...

Categories