0

If I bind the function find in javascript, I can do the following:

const _array = [4,10,6,5,20];

const loop = Array.prototype.find.bind(_array);
const r = loop(function (x) {
    return x === 6;
});

console.log(`Final result => ${r}`); // here prints: Final result => 6

As you can see, in the binded loop function I have a callback returned from find. Everything works and it's ok ...

But, trying to simulate something like that I ended with this:

function loop(a,callback) {
    for(i=0;i<a.length;i++)
        callback(a[i]);
};

const r = loop([4,10,6,5,20], function (x) {
    console.log("x value", x);
    return x===6; // need to break the loop function and return to 'r' the 'x' value
});

console.log(`Final result => ${r}`); // here would print the value of x, that would be 6

and I get:

x value 4
x value 10
x value 6
x value 5
x value 20
undefined

what means that the return x===6 inside the r function is not working correctly, because the for-loop continues to the end.

So, my question:

How can I break the loop function when x===6 and return the value of x ?

robe007
  • 3,523
  • 4
  • 33
  • 59
  • Uh, your `loop` function behaves like `forEach`, not like `find`? – Bergi Sep 27 '18 at 19:01
  • @Bergi That's why I'm asking. – robe007 Sep 27 '18 at 19:07
  • So you're essentially asking "*[How to implement `find`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill) myself?*", right? – Bergi Sep 27 '18 at 19:10
  • @Bergi Not exactly, just I took the `find` function as an example, but my question is about on how to return from the callback inside the `for-loop`. That's it. – robe007 Sep 27 '18 at 19:13
  • The answer to that question is: you can't in general. The callback doesn't control how often it is called or what `loop` returns, it also cannot just "jump out" of control flow (except you're considering exceptions, but even those can be caught). The only way is to make the `loop` function react to the return value of the callback call. – Bergi Sep 27 '18 at 19:20
  • @Bergi Yeah sure, that's why the use of an `if` in the answer below. And talking about the use of `exceptions`, I was reading that they are used in a `foreach`, because inside of it I can't return. See [here](https://stackoverflow.com/a/2641374/2954267) – robe007 Sep 27 '18 at 19:26

2 Answers2

2

Check what value is returned by the callback, and then decide whether to continue or not:

function loop(a, callback) {
  for (let i = 0; i < a.length; i++) {
    const found = callback(a[i]);
    if (found) {
      return a[i];
    }
  }
}

const r = loop([4,10,6,5,20], function (x) {
  console.log("x value", x);
  return x===6;
});

console.log(`Final result => ${r}`);
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
1

You can also write find using recursion

const find = (f, [ x, ...xs ]) =>
  x === undefined
    ? null
  : f (x) === true
    ? x
  : find (f, xs)

console.log
  ( find
      ( x => x > 8
      , [ 5, 7, 9, 3, 1 ]
      )
      // 9
      
  , find
      ( x => x < 4
      , [ 5, 7, 9, 3, 1 ]
      )
      // 3
  )

Instead of destructuring assignment, an index parameter can be used

const find = (f, xs = [], i = 0) =>
  i >= xs.length
    ? null
  : f (xs[i]) === true
    ? xs[i]
  : find (f, xs, i + 1)

In both cases, iteration through the array stops as soon as f returns true

Mulan
  • 129,518
  • 31
  • 228
  • 259
  • I think your parameters need to be swapped. The `array` in the question is the first parameter, not the second. Also recursion is going to cause a stack overflow error for large arrays, so I don't recommend this approach. – Patrick Roberts Sep 27 '18 at 19:17
  • PS there's [many ways](https://stackoverflow.com/a/43596323/633183) to avoid overflowing the stack – Mulan Sep 27 '18 at 20:18