1

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.

2
  • 2
    You return from the function - why would you expect THAT to have any effect on the for loop? Your function does an implicit return anyway even if you leave out that word, by the way. Commented Dec 21, 2014 at 22:58
  • Break is defined only for loops, switches or labels in the spec. Commented Dec 21, 2014 at 22:59

2 Answers 2

2

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).

Sign up to request clarification or add additional context in comments.

1 Comment

Really appreciate this answer - very concisely and clearly written with good examples.
0

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]).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.