Why does .forEach() return undefined?

Why is the return value for .forEach() always undefined?

const fruits = ['mango', 'papaya', 'pineapple', 'apple'];

// Iterate over fruits below
fruits.forEach( fruit => {
  let indefiniteArticle = '';
  if (fruit[0] === 'a' || fruit[0] === 'e' || fruit[0] === 'i' || fruit[0] === 'o' || fruit[0] === 'u') {
    indefiniteArticle = 'an';
  } 
  //else if (fruit[0] === 'h'&& fruit[1] ===) { }
  else {
    indefiniteArticle = 'a';
  }
  console.log(`I want to eat ${indefiniteArticle} ${fruit}`);
});

/* Added indefinate article conditions. 
For future senerio, implment conditions with words starting with an H.
Also obeying DRY, create an array of vowels to loop through to avoid rewriting each vowels condition on the H comparison. */

I included Indefinate Article conditions to make an apple grammatically correct.

why would this method need to return anything? What matters are the values you get from the array

1 Like

Hi
MDN and the instruction in the Codecademy say that .forEach() always return undefined!!
The question is why and even how we can get this while in codes I’ve seen, it always return something but undefined!

Array.forEach() does return undefined, but never anything else. It iterates over an array and acts upon its elements in the manner we instruct by way of our callback.

Let’s demonstrate this…

 > function print (x) {
     console.log(x);
     return 0;
   }
<- undefined
 > [1,2,3,4,5,6,7,8,9].forEach(print)
   1
   2
   3
   4
   5
   6
   7
   8
   9
<- undefined

The last line is the echoed response to the command entered.

 > print([1,2,3,4,5,6,7,8,9].forEach(print))
   1
   2
   3
   4
   5
   6
   7
   8
   9
   undefined
<- 0

The 0 is the return from the print function. It is ignored by the iterator when the function is given as a callback.

 > console.log([1,2,3,4,5,6,7,8,9].forEach(print))
   1
   2
   3
   4
   5
   6
   7
   8
   9
   undefined
<- undefined

The last value is the logged return from .forEach().

1 Like

What does it mean the: The return value for .forEach() will always be undefined

Thank you

 > list = [1, 2, 3, 4, 5, 6]
 > console.log(list.forEach(x => x * 2))
   undefined
<- undefined
 > console.log(list.map(x => x * 2))
<- [2, 4, 6, 8, 10, 12]
<- undefined

One method has no return value, the other does.

Could you explain what you are trying to do here? Is this from the first lesson in the

The .forEach() Method

Thank you.

console.log(`I want to eat ${`aeiou`.includes(fruit.charAt(0)) ? `an` : `a`} ${fruit}.`);

The above does the same thing as the earlier example without using if..else.

As in,

const fruits = ['mango', 'orange', 'papaya', 'pineapple', 'apple', 'banana', 'apricot'];
wantToEat = fruit => console.log(`I want to eat ${`aeiou`.includes(fruit.charAt(0)) ? `an` : `a`} ${fruit}.`);
fruits.forEach(wantToEat);
I want to eat a mango.
I want to eat an orange.
I want to eat a papaya.
I want to eat a pineapple.
I want to eat an apple.
I want to eat a banana.
I want to eat an apricot.

Because in this function we don’t use return. if you want to see undefined you can print:
console.log(fruits.forEach(oneFruit => console.log('I want to eat a ’ + oneFruit)))

So basically the method will return undefined but it will also return the command that we set in stone right? Also why would I need to use a method that will give me undefined. What is its purpose and how to make full use of it?

what do you mean by this? a function can only a return one thing

undefined can mean you don’t have to do anything with the returned result.

Not so much, ‘return’, as carry out prescribed steps on each item in the array it is called upon. In as much, it is not far off from an ordinary for loop except that it is a higher order function that takes a callback, and it has no way of diversion (cannot use break).

Anytime we wish to perform an action on every item in an array this is a great iterator to reach for. The convenience of a callback which can take both a value and an index, along with optional pass-along arguments only adds to its utility.

Consider using it to enumerate a list (an array)…

a = ['zero', 'one', 'two', 'three', 'four', ]
b = []
a.forEach((x, i) => b.push([i, x])
console.log(b)
/*
[
  [0, "zero"],
  [1, "one"],
  [2, "two"],
  [3, "three"],
  [4, "four"]
]
*/

Now for some silliness…

const f = (x, i) => b.push([i, x])
const g = (x, i) => b.push([x, i])
a = ['zero', 'one', 'two', 'three', 'four' ]
b = []
a.forEach(this.length % 2 ? f : g)
console.log(b)
/*
[
  [0, "zero"],
  [1, "one"],
  [2, "two"],
  [3, "three"],
  [4, "four"]
]
*/
a = ['zero', 'one', 'two', 'three', 'four', 'five' ]
b = []
a.forEach(this.length % 2 ? f : g)
console.log(b)
/*
[
  ["zero", 0],
  ["one", 1],
  ["two", 2],
  ["three", 3],
  ["four", 4],
  ["five", 5]
]
*/

Okay so what is return mean what does it do? Is it always necessary I know that in arrow notation depending on the code written after the code you can either not add return or opt out of it. But I’m not sure about it’s purpose in most cases.

literally what it says, returning (handing back) data to the caller.

here is an example:

const example = () => {
  let abc = 'def';
  return abc;
}

result = example();
console.log(result);

without return, we wouldn’t be able to access the abc variable.

We don’t necessarily opt in or out, as much as accept that a single expression on one line without curly braces is implicitly returned. Note @stetim94’s example above where there are multiple statements. There is nothing optional there. The curly braces must be used to define the block, and if a return is expected, then it must be written explicitly in the function body.

Technically speaking, our examples above don’t need a return since the action is taking place on a global object, the array, b.

We must never get into thinking that anything is ‘set in stone’, as you put it earlier. There are any number of possibilities in terms of how we design our code. Just remember, we are the designers, and are not held to any gold standard apart from valid syntax. The logic is entirely up to us. When we wish to make use of the data created in a function then our best plan is to return that data to the caller. It can be stored at that point (and in that scope) and recalled later by another part of the program.

Our earlier callbacks can be written in conventional syntax with the exact same effect.

const f = function(x, i) {
  b.push([i, x]);
}

In either case, with or without a return it won’t matter since forEach() does not expect a return (from the callback), nor will it process one in any event. The above function will return undefined. The earlier arrow function callbacks do return something, the new length of the array, which is inconsequential and ignored.

Of all the iterators, I believe forEach() is the only one that will return undefined. In cases where a return is needed then we would need to reach for one of the other iterators, such as map().

Bottom line, if return is still causing you some concern then the best I can suggest is go back to the beginning of the functions unit and review the narratives and exercises, and do a little digging in the documentation. Once you are clear on its use, you will be better able to design code and know when and when not to include it.