Javascript - how to break or return value in forEach

Javascript has built-in function forEach

example

var tab = ['a', 'b', 'c'];

tab.forEach(function(el, i) {
  console.log(el, i);
});
Output:
a 0
b 1
c 2
What if we want to break forEach? In java or c sharp you can use break


Break doesn't work in forEach because this is not for.

SyntaxError: unlabeled break must be inside loop or switch

So maybe return?


var tab = ['a', 'b', 'c'];

tab.forEach(function(el, i) {
  console.log(el, i);
    if (el == 'b') {
     return; 
  }
});
Output:
a 0
b 1
c 2
Output is the same :( Why? Because return works only for current function, not entire forEach. So this works like continue

So what to do?


1) Use external libraries
For example jquery .each() supports breaks. We need to return false; 
var tab = ['a', 'b', 'c'];

$(tab).each(function(i, el) {
  console.log(el, i);
    if (el == 'b') {
     return false; 
  }
});Output: 
a 0
b 1
  But jquery .each doesn't support returning value and its usage is less convenient - you need to wrap table to $() and first argument is index.
2) Custom function 
Let's write out better forEach :)
 
var each = function (func) {
    var len = this.length;
    if (typeof func !== "function") {
        throw new TypeError();
    }
    var thisp = arguments[1];
    for (var i = 0; i < len; i++) {
        if (i in this) {
            var result = func.call(thisp, this[i], i, this);
            if (result !== undefined) {
                return result;
            }
        }
    }
};

Object.defineProperty(
    Array.prototype, 'each', {enumerable: false, get: function() { return each; } });
 
This 'forEach' supports returning any value (not only breaks), indexes and passing this.
Why I used  
Object.defineProperty instead of Array.prototype.each = function ... ?
Because in Object.defineProperty we can set enumerable: false so it is not visible in for (var i in tab) {}

Although in for (var i in tab) you should check hasOwnProperty many people don't do it :(

You can add new function 'each' or overwrite built-in 'forEach'
Some tests in jasmine:
'use strict';

describe('Each function', function () {

    it('should pass "this" to function', function () {

        this.id = 2;

        var tab = [2, 3, 4, 5];
        var count = 0;

        tab.each(function(el, i) {
            count += this.id;
        }, this);

        expect(count).toBe(8);
    }, 1200000);

    it('should continue on return', function () {
        var tab = [2, 3, 4, 5];
        var count = 0;

        tab.each(function(el, i) {
            if (i> 0) {
                return;
            }
            count++;
        });

        expect(count).toBe(1);
    }, 1200000);

    it('should not be enumerable on array', function () {
        var tab = [2, 3, 4, 5];
        var count = 0;

        for (var i in tab) {
            count++;
        }


        expect(count).toBe(4);


    }, 1200000);

    it('should execute on each element', function () {
        var tab = [2, 3, 4, 5];

        var sumValues = 0;
        var sumIndexes = 0;

        tab.each(function(el, i) {
            sumValues += el;
            sumIndexes += i;
        });

        expect(sumValues).toBe(14);
        expect(sumIndexes).toBe(6);


    }, 1200000);

    it('should break foreach', function () {
        var tab = ["a", "b", "c", "d"];
        var loopNo = 0;

         tab.each(function(el, i) {
            if (i == 2) {
                return false;
            }
            loopNo++;
        });

        expect(loopNo).toBe(2);


    }, 1200000);

    it('should return value', function () {
        var tab = ["a", "b", "c", "d"];

        var result = tab.each(function(el, i) {
            if (i == 2) {
                return el;
            }
        });

        expect(result).toBe("c");


    }, 1200000);



})
;