2

I have a for loop in JavaScript like

var loopvariable = 0;  
let row = [[]];
for (var key in supplies.food) {
     row[loopvariable][0] = key;
     row[loopvariable][1] = supplies.food[key];
     loopvariable++;
}

why am i getting the following error

TypeError: row[loopvariable] is undefined

akshay kishore
  • 1,017
  • 8
  • 16
  • For future questions, please include a [mcve] demonstrating the problem, ideally a **runnable** one using Stack Snippets (the `[<>]` toolbar button; [here's how to do one](https://meta.stackoverflow.com/questions/358992/)). You've said in a comment on my answer that `supplies.food` is an array. That's surprising, because `for-in` isn't the correct way to loop through arrays. If you provide complete information, it makes it possible to help you better. – T.J. Crowder Aug 28 '18 at 08:13

2 Answers2

4

TL;DR

Object.entries provides exact the output you're trying to create there:

let row = Object.entries(supplies.food);

Details, and why your code isn't working

You've only created an array at row[0], not at row[1] (row[2], row[3], ...), but then you're trying to use an array at row[1] on the second iteration of the loop.

The minimal change is to leave the creation of the inner arrays to the loop body:

var loopvariable = 0;  
let row = [];                                      // ***
for (var key in supplies.food) {
     row[loopvariable] = [];                       // ***
     row[loopvariable][0] = key;
     row[loopvariable][1] = supplies.food[key];
     loopvariable++;
}

But we can also use an array initializer to be more concise:

var loopvariable = 0;  
let row = [];
for (var key in supplies.food) {
     row[loopvariable++] = [
         key,
         supplies.food[key]
     ];
}

But, again, for this specific case you can just use Object.entries:

let row = Object.entries(supplies.food);

Live Example:

const supplies = {
  food: {
    water: "3l",
    bread: "2 loaves",
    chocolate: "4 bars"
  }
};
let row = Object.entries(supplies.food);
console.log(row);

Object.entries is supported in all modern environments, and easily polyfilled in older environments.

In a comment you've said supplies.food is an array. If so, for-in isn't the right way to loop through it (see this answer for details), but Object.entries still works because arrays are objects, too (see my blog post for more):

const supplies = {
  food: [
    "3l water",
    "2 loaves bread",
    "4 bars chocolate"
  ]
};
let row = Object.entries(supplies.food);
console.log(row);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @akshaykishore - Actually, looking at the array you're producing, it's exactly what you'd get from `Object.entries`, I've added to the end of my answer. – T.J. Crowder Aug 28 '18 at 07:57
  • actually food here is an array not an object so i don't know if that'll work or not – akshay kishore Aug 28 '18 at 08:00
  • @akshaykishore - Yes, it will (because arrays are objects, too). But `for-in` isn't the right way to loop through arrays. I've added to the end of the answer with details. – T.J. Crowder Aug 28 '18 at 08:11
4

The variable

row[loopvariable]

is not initialized. You could use a default value and take an array with a guard operator (logical OR ||).

row[loopvariable] = row[loopvariable] || [];

A shorter approach could be just to push a new array to row, without using an aditional variable loopvariable

let row = [];
for (var key in supplies.food) {
    row.push([key, supplies.food[key]]);
}
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392