Why is .forEach returning undefined?

2020-05-10 08:26发布

问题:

I know there already are multiple questions to this topic https://stackoverflow.com/search?q=%5Bjavascript%5D+return+forEach+undefined but none of this seemed to help me out.

So I have the following data:

 const testsMap = {
            0: ["just", "test"],
            1: ["bla", "asdf"]
        }

 const testArray = [{
    id: "1",
    segments: null,
    tests: [{
            id: "1",
            segments: "1"
        },
        {
            id: "2",
            segments: "0"
        }
    ]
},
{
    id: "2",
    segments: "1",
    tutorials: [{
            id: "1",
            segments: "1"
        },
        {
            id: "2",
            segments: "0"
        }
    ]
}];

What I want to achieve with the output without using .map() or .reduce since I do not want a new array, I just want to overwrite the existing one, is the following:

[{
    display: true,
    id: "1",
    segments: null,
    tests: [{
            display: true,
            id: "1",
            segments: "1",
            newSegments: ["bla", "asdf"]
        },
        {
            display: true,
            id: "2",
            segments: "0",
            newSegments: ["just", "test"]
        }
    ]
},
{
    display: false,
    id: "2",
    segments: "1",
    tutorials: [{
            id: "1",
            segments: "1"
        },
        {
            id: "2",
            segments: "2"
        }
    ]
}];

The function I have looks something like this - please note that it has some helper fns which you can ignore - it's just about that the fn returns undefined:

function SOtest () {
  const returnedValue = testArray.forEach(test => {
    test.newSegments = test.segments ? testsMap[test.segments] : [];
    test.display = helperFn(); // will add true/false to the test prop

    if (test.display) {
      test.tests.map(t => {
        t.newSegments = t.segments ? testsMap[t.segments] : [];
        t.display = helperFn(); // will add true/false to the test prop
      })
    }
    return test;
  })
  return returnedValue;
}

Now the forEach itself works just fine when executed by itself in the console - but as soon as I want to return it, it equals undefined.

What am I missing?

回答1:

forEach doesn't return anything. It just loops through elements and while looping you can change element data

And so you can change your function SOtest to

function SOtest () {
  testArray.forEach(test => {
    test.newSegments = test.segments ? testsMap[test.segments] : [];
    test.display = helperFn(); // will add true/false to the test prop

    if (test.display) {
      test.tests.map(t => {
        t.newSegments = t.segments ? testsMap[t.segments] : [];
        t.display = helperFn(); // will add true/false to the test prop
      })
    }
  })
  return testArray;
}


回答2:

According to mdn forEach

forEach() executes the callback function once for each array element; unlike map() or reduce() it always returns the value undefined and is not chainable. The typical use case is to execute side effects at the end of a chain.



回答3:

According to MDN:

.map() returns "A new array with each element being the result of the callback function."

.forEach() returns undefined.

If the code you're looping through is meant to be contiguous, use .map(), otherwise the .forEach() is fine.

Sources:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map