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.
So maybe return?
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 usedObject.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); }) ;