book_lover63
book_lover63

Reputation: 25

Why is 'break' in JS forEach function not allowed?

I've done quite a bit of reading and seen many different questions regarding this topic, but I was wondering if I could get help on WHY breaking out of a For Each loop doesn't work. Also, I am pretty new, so I apologize in advance if this question was answered in a different way that I wasn't able to understand.

So far, I have written a forEach function to emulate a native .forEach method:

function forEach(collection, callback){
  if(collection.isArray){
    for(var i =0;i<collection.length&&callback(collection[i])!==false;i++){
      callback(collection[i]);
    }
  }else{
    for(var key in collection){
      callback(collection[key]);
    }
  }
}

When I try to utilize this to write another function 'find' that searches for the first instance of the array that matches a criteria, using 'return' or 'break' doesn't seem to work. find([1,2,3,4,5].function(x){return x>3;}); returns 5 instead of 4.

function find (collection, criteria){
  var result;
  forEach(collection, function(x){
    if(criteria(x)){
      result =x;
      return false;
    }
  });
  return result;
}

I have been able to recreate the effect that I want using other functions, but would like to understand why this doesn't work, as I am learning how to implement the use of functions within other functions.

Thank you.

Upvotes: 1

Views: 290

Answers (2)

fgb
fgb

Reputation: 18559

For an array, collection.isArray is undefined. You should replace this with Array.isArray(collection).

For non-array types, you're not checking the return value of callback(collection[key]).

Upvotes: 0

icktoofay
icktoofay

Reputation: 129149

Consider the behavior of bar in this code snippet:

function foo(x) {
    return x;
}

function bar() {
    foo(1);
    foo(2);
    return 3;
}

console.log(bar());

It calls foo, which returns, but it is returning control back to bar itself, not to the caller of bar, so this logs 3.

The situation does not change if we put the definition of foo inside bar:

function bar() {
    function foo(x) {
        return x;
    }

    foo(1);
    foo(2);
    return 3;
}

console.log(bar());

Nor does it change if we accept it as a parameter:

function foo(x) {
    return x;
}

function bar(baz) {
    baz(1);
    baz(2);
    return 3;
}

console.log(bar(foo));

The behavior does not change when we use a function expression, either:

function bar(baz) {
    baz(1);
    baz(2);
    return 3;
}

console.log(bar(function(x) {
    return x;
}));

So the reason return does not work the way you are expecting from a function passed to forEach is that return retains its usual meaning of returning from the function it is in—not the function that lexically encloses that function. Similarly, break is illegal because it is not in a loop; it is in a function (that only happens to be called in a loop later on).

Upvotes: 2

Related Questions