Your example is a bit odd, but as this question is becoming the canonical "return from forEach
" question, let's use something simpler to demonstrate the problem:
Here, we have a function that checks the entries in an array to see if someProp
matches value
and, if so, increments the count
on the entry and returns the entry:
function updateAndReturnMatch(array, value) {
array.forEach(function(entry) {
if (entry.someProp == value) {
++entry.count;
return entry;
}
});
}
But calling updateAndReturnMatch
gives us undefined
, even if the entry was found and updated.
The reason is that the return
inside the forEach
callback returns from the callback, not from updateAndReturnMatch
. Remember, the callback is a function; return
in a function returns from that function, not the one containing it.
To return from updateAndReturnMatch
, we need to remember the entry and break the loop. Since you can't break a forEach
loop, we'll use some
instead:
function updateAndReturnMatch(array, value) {
var foundEntry;
array.some(function(entry) {
if (entry.someProp == value) {
foundEntry = entry;
++foundEntry.count;
return true; // <== Breaks out of the `some` loop
}
});
return foundEntry;
}
The return true
returns from our some
callback, and the return foundEntry
returns from updateAndReturnMatch
.
Sometimes that's what you want, but often the pattern above can be replaced with Array#find
, which is new in ES2015 but can be shimmed for older browsers:
function updateAndReturnMatch(array, value) {
var foundEntry = array.find(function(entry) {
return entry.someProp == value;
});
if (foundEntry) {
++foundEntry.count;
}
return foundEntry;
}