DEV Community

Discussion on: Ways to loop in an array using the different types of "FOR LOOP" in Javascript.

Collapse
 
peerreynders profile image
peerreynders

Being an array method .forEach() is really the only one that is limited to arrays.

Note that eslint no-constant-condition won't tolerate while(true) but will accept for(;;).

let count = 0;
for(;;) {
  if (count < 3) {
    console.log(count);
    count += 1;
    continue;
  }

  break;
}
Enter fullscreen mode Exit fullscreen mode

As the reference linked to states:

The for...in statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties.

(… and arrays are "special objects")

const special = Symbol('special');
const grades = [];
grades.a = 1;
grades[0] = 80;
grades.c = 3;
grades[1] = 85;
grades.b = 2;
grades[2] = 90;
grades[special] = 42;

console.log(grades[special]);
console.log(grades.hasOwnProperty('1')); // as a string
console.log(grades.hasOwnProperty(1)); // as a number
console.log(grades.hasOwnProperty(special)); // as a symbol

for (const key in grades) {
  console.log(`${keyToString(key)}: ${grades[key]}`);
}

function keyToString(key) {
  switch (typeof key) {
    case 'symbol':
      return 'some symbol';
    case 'string':
      return `'${key}'`;
  }

  return key.toString();
}

console.log('Just keys()');
for (const key of grades.keys()) {
  console.log(`${keyToString(key)}: ${grades[key]}`);
}

/*
42
true
true
true
"'0': 80"
"'1': 85"
"'2': 90"
"'a': 1"
"'c': 3"
"'b': 2"

"Just keys()"
"0: 80"
"1: 85"
"2: 90"

Note how 'in' always produces "string"s
While '.keys()' used with 'of' actually returns "number"s
 */
Enter fullscreen mode Exit fullscreen mode

As the reference linked to states:

The for...of statement creates a loop iterating over iterable objects, including: built-in String, Array, array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined iterables.

const special = Symbol('special');
const entries = [
  ['0', 1],
  [0, 80],
  ['2', 3],
  [1, 85],
  ['1', 2],
  [2, 90],
  [special, 42],
];
const someMap = new Map(entries);

for (const [key, value] of someMap) {
  console.log(`${keyToString(key)}: ${value}`);
}

function keyToString(key) {
  switch (typeof key) {
    case 'symbol':
      return 'some symbol';
    case 'string':
      return `'${key}'`;
  }

  return key.toString();
}

/*
"'0': 1"
"0: 80"
"'2': 3"
"1: 85"
"'1': 2"
"2: 90"
"some symbol: 42"
 */
Enter fullscreen mode Exit fullscreen mode

Bonus: Both for...in and .forEach() will skip "holes" ("empty values") in arrays while for...of , .keys() and .entries() will not.

const grades = [80, undefined, , 95]; // hole/empty at index 2

console.log(grades.hasOwnProperty(1)); // true - value undefined
console.log(grades.hasOwnProperty(2)); // false - hole
console.log(grades.hasOwnProperty(3)); // true - number 95

const show = (value, key) => console.log(`${keyToString(key)}: ${value}`);

for (let key = 0; key < grades.length; key += 1) show(grades[key], key);
/*
"0: 80"
"1: undefined"
"2: undefined"
"3: 95"
*/

for (const key in grades) show(grades[key], key);
/*
"'0': 80"
"'1': undefined"
"'3': 95"

i.e. key '2' was skipped
*/

for (const value of grades) console.log(value);
/*
80
undefined
undefined
95
*/

for (const [key, value] of grades.entries()) show(value, key);
/*
"0: 80"
"1: undefined"
"2: undefined"
"3: 95"
*/

grades.forEach(show);
/*
"0: 80"
"1: undefined"
"3: 95"

i.e. index 2 was skipped
*/

function keyToString(key) {
  switch (typeof key) {
    case 'symbol':
      return 'some symbol';
    case 'string':
      return `'${key}'`;
  }

  return key.toString();
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kidxs profile image
Angelo Geant Gaviola

Thank you so much for shedding some light!