12
Object.prototype.e = function() { [].forEach.call(this, function(e) { return e; }); }; var w = [1,2]; w.e(); // undefined 

But this works if I use alert instead

// ... [].forEach.call(this, function(e) { alert(e); }); // ... w.e(); // 1, 2 
4
  • What would you expect the first one to do? Commented Aug 26, 2011 at 19:54
  • 4
    I don't understand, did you want to use .map? And please, don't put enumerable properties on Object.prototype! Commented May 16, 2013 at 17:18
  • 2
    @Bergi I honestly don't remember what I was thinking back then. I was a beginner, sorry. lol Commented May 16, 2013 at 17:32
  • A lot of these answers focus on callbacks but, at least for newcomer me, the issue was I expected .forEach to function like .map. Adding this comment to give more attention to Bergi's recommendation of .map Commented Mar 3, 2022 at 23:34

5 Answers 5

10

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; } 
Sign up to request clarification or add additional context in comments.

2 Comments

@squint: Yup, I flagged that up in a comment. But I couldn't come up with a better example. My lack of creativity. :-|
@squint: I think I came up with a better example.
8

I realize this is an old question, but as it's the first thing that comes up on google when you search about this topic, I'll mention that what you're probably looking for is javascript's for.. in loop, which behaves closer to the for-each in many other languages like C#, C++, etc...

for(var x in enumerable) { /*code here*/ } 

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in

http://jsfiddle.net/danShumway/e4AUK/1/

A couple of things to remember :

  • for..in will not guarantee that your data will be returned in any particular order.
  • Your variable will still refer to the index, not the actual value stored at that index.
  • Also see below comments about using this with arrays.

edit: for..in will return (at the least) added properties to the prototype of an object. If this is undesired, you can correct for this behavior by wrapping your logic in an additional check:

for(var x in object) { if(object.hasOwnProperty(x)) { console.log(x + ": " + object[x]); } } 

2 Comments

Perhaps not such a great idea: stackoverflow.com/questions/500504/…
A good distinction to make is that (for.. in) can be misused on arrays (and similar data types), but is largely not considered bad practice when used on other user-defined objects (especially where data-types like JSON are concerned), at least not in the coding circles I frequent. The most important thing when using (for... in) is to keep track of who is touching your objects and whether or not they're attaching any extra properties onto them. Outside of that, the only real disadvantages are JS quirks that might catch you by surprise.
7

The function e() isn't returning anything; the inner anonymous function is returning its e value but that return value is being ignored by the caller (the caller being function e() (and can the multiple uses of 'e' get any more confusing?))

Comments

7

Because

function(e) { return e; } 

is a callback. Array.forEach most likely calls it in this fashion:

function forEach(callback) { for(i;i<length;i++) { item = arr[i]; callback.call(context, item, i, etc.) } } 

so the call back is called, but the return doesn't go anywhere. If callback were called like:

return callback.call(); 

the it would return out of forEach on the first item in the array.

Comments

0

You can use for...of to loop over iterable objects, like array, string, map, set... as per Mozilla docs.

const yourArray = [1, 2, 3] for (const el of yourArray) { // or yourMap, Set, String etc.. if (el === 2) { return "something"; // this will break the loop } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.