-2

It seems like map, forEach, filter and this sort of operators don't work with string-indexed arrays like so:

let a = [];
a['first element'] = 1;
a['second element'] = 2;
a['third element'] = 3;
a.forEach(console.log)
//undefined
dinigo
  • 6,872
  • 4
  • 37
  • 48
  • Side note: In most environments, you'll likely be a bit surprised by what you see from `someArray.forEach(console.log);` Some environments may throw an error (because `log` is called with `this` not referring to `console`). Others may work but show you something you don't expect such as three things for each loop iteration instead of one. That's because most `console.log` implementations log **all** arguments they receive, and `forEach` calls its callback with three arguments: The entry, its index, and the array reference. :-) – T.J. Crowder Apr 06 '17 at 16:43

3 Answers3

2

That's because it's not a "string-indexed array." JavaScript doesn't have those. What you have there is an array (because you used []) but you're not using it as an array, you're using it as an object. (Arrays are also objects; see my A myth of arrays.) Those are object property names. If you're not using the array-ness of it, use {} instead of [] to create it.

There are a couple of operations that iterate property names:

  • You can get an array of an object's own, enumerable property names via Object.keys. There's also Object.getOwnPropertyNames.
  • You can loop through all enumerable properties (including inherited ones) with a for-in loop.
  • Plain objects aren't iterable, so we can't use for-of, but if you want something like a "string-indexed array" you might look at Map, which is iterable.

Here are a couple of examples:

let a = {};
a['first element'] = 1;
a['second element'] = 2;
a['third element'] = 3;
console.log("for-in:");
for (let key in a) {
  console.log(key);
}
console.log("Object.keys:");
Object.keys(a).forEach(key => console.log(key));
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

First of all, you are making an object.

a['first element'] = 1;
   ^^^^^ -> key      ^ -> it's value

If you want to assign specified elements into the array, refer to the a array and it's specified index - e.g. [0] and assign some value, e.g. 1.

And about the Array#forEach functio - if you want to log each element, you have to pass an argument which will hold every element from the array.

let a = [];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a.forEach(v => console.log(v))
kind user
  • 40,029
  • 7
  • 67
  • 77
0

That's because when you access an array like this:

a['first element']

You're not accessing an array element. You putting a property in the array object.

You can access properties in a javascript objects in two ways: obj.property or obj['property']. An array is an object like any other, which has some methods to put elements in the array (.push), but as it's an object, besides the elements it may have other properties. It already has some (like .length). So you're just including more.

For your pupose (maps) instead of using an array object, you can use an empty object. Like this:

let a = {};
a['first element'] = 1;
a['second element'] = 2;
a['third element'] = 3;
// then you use for...in instead of forEach:
for(element in a) {
   // and get the value of the property in the element like this:
   console.log(a[element]);
}

There's also the newer Map and WeakMap objects. You want to take a look at them here's the link: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Map

Here is an example using Map:

var a = new Map();
a.set('first element', 1);
a.set('second element', 2);
a.set('third element', 3);
for (var [key, value] of a) {
  console.log(key + ": " + value);
}
// Now you can also use forEach
a.forEach((value, key)=>console.log(key + ": " + value));
Nelson Teixeira
  • 6,297
  • 5
  • 36
  • 73