8

I wonder if forEach in JavaScript can make a return, here is my code:

var a = [0, 1, 2, 3, 4];

function fn(array) {
  array.forEach(function(item) {
    if (item === 2) return false;
  });

  return true;
}

var ans = fn(a);
console.log(ans); // true

I want to find out if 2 is in my array, if so, return false, but it seems that the forEach function has looped the whole array and ignore return.

I wonder if I can get the answer I want with forEach ( I know I can get what I want using for(..))? dear friend, pls help me, with great thanks!

hanzichi
  • 609
  • 2
  • 12
  • 22
  • There is a rather ugly workaround at http://stackoverflow.com/a/22187463/14955 – Thilo Aug 17 '15 at 02:24
  • Oh, wait - you want to know if you can return a value from the overall iteration? In that case, see my answer about using `.reduce()`. – Pointy Aug 17 '15 at 02:28

6 Answers6

8

You can use indexOf instead https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

function fn(array) {
  return (array.indexOf(2) === -1);
}

Also from the documentation for forEach - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

Note: There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behaviour, the .forEach() method is the wrong tool, use a plain loop instead.

So, the return value cannot be used the way you are using it. However you could do a throw (which is not recommended unless you actually need an error to be raised there)

function fn(array) {
  try {
      array.forEach(function(item) {
         if (item === 2) throw "2 found";
      });
  }
  catch (e) {
    return false;
  }

  return true;
}
potatopeelings
  • 40,709
  • 7
  • 95
  • 119
  • my code is just a sample, my real purpose is to find weather a repeated item in a an array by using forEach... – hanzichi Aug 17 '15 at 02:23
  • @ZichiHan - I just edited my answer to cover that too. Short answer - you need to use a throw if you must do it that way. Cheers! – potatopeelings Aug 17 '15 at 02:24
  • Why do you think *try..catch* is required? – RobG Aug 17 '15 at 02:42
  • @RobG - I think its not required and not recommended (see the bold portion in my answer). I was just illustrating how you can exit the forEach loop (since OP was wondering why it wasn't working and as mentioned in the MDN blockquote). Hope that's not too confusing. Cheers! – potatopeelings Aug 17 '15 at 03:23
4

In this case .indexOf() is probably what you want, but there's also .some() when a simple equality comparison is too simple:

var ans = a.some(function(value) { return value === 2; });

The .some() function returns true if the callback returns true for any element. (The function returns as soon as the callback does return true, so it doesn't bother looking beyond the first match.)

You can usually use the .reduce() function as a more general iteration mechanism. If you wanted to count how many instances of 2 were in your array for example:

 var twos = a.reduce(function(c, v) { if (v === 2) c += 1; return c; }, 0);
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • my code is just a sample, my real purpose is to find weather a repeated item in a an array by using forEach... – hanzichi Aug 17 '15 at 02:25
  • @ZichiHan I don't understand what that means. Do you want to see if there is some particular item in an array more than once? – Pointy Aug 17 '15 at 02:27
  • @ZichiHan oh wait, maybe I do understand - I think you should use `.reduce()` as I explain above. – Pointy Aug 17 '15 at 02:28
1

forEach returns undefined by specification. If you want to find out if a particular value is in an array, there is indexOf. For more complex problems, there is some, which allows a function to test the values and returns true the first time the function returns true, or false otherwise:

a.some(function(value){return value == 2})

Obviously a trivial case, but consider if you want to determine if the array contains any even numbers:

a.some(function(value){return !(value % 2)})

or as an ECMA2015 arrow function:

a.some(value => !(value % 2));

If you want to test if a particular value is repeated in an array, you can use lastIndexOf:

if (a.indexOf(value) != a.lastIndexOf(value) {
  // value is repeated
}

or to test for any duplicates, again some or every will do the job:

var hasDupes = a.some(function(value, i, a) {
  return a.lastIndexOf(value) != i;
});

An advantage of some and every is that they only process members of the array until the condition is met, then they exit whereas forEach will process all members regardless.

RobG
  • 142,382
  • 31
  • 172
  • 209
1

Others have mentioned .indexOf() and .some(). I thought I would add that a good old fashioned for loop gives you the absolute most iteration control because you control the iteration and your processing code is not embedded in a callback function.

While .indexOf() already does exactly what you need, this code just shows how you can directly return when using the old fashioned for loop. It is somehow out of favor these days, but is often still the best choice for better looping control.

function fn(array) {
  for (var i = 0, len = array.length; i < len; i++) {
    if (array[i] === 2) return false;
  }
  return true;
}

Using the for loop, you can iterate backwards (useful when removing items from the array during the iteration), you can insert items and correct the iteration index, you can immediately return, you can skip indexes, etc...

jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

You said you want with forEach, so I modified your code:

function fn(array) {
    var b = true;
    array.forEach(function (item) {
        if (item === 2) {
            b = false;
        }
    });
    return b;
}
Paul S.
  • 64,864
  • 9
  • 122
  • 138
如果有时间
  • 205
  • 1
  • 2
  • 10
0

var a = [0, 1, 2, 3, 4];

function fn(array, callback) {
  var r = true;
  array.forEach(function(item) {
    if (item === 2) r = false;
  });

  callback(r);
}

fn(a, function(data) {
console.log(data) //prints false.
});

You can use callbacks as mentioned above to return the data you need. This is not same as the return statement but you will get the data.

Krishnadas PC
  • 5,981
  • 2
  • 53
  • 54