先来看下forEach的实现
// Production steps of ECMA-262, Edition 5, 15.4.4.18// Reference: http://es5.github.io/#x15.4.4.18if (!Array.prototype.forEach) { Array.prototype.forEach = function(callback, thisArg) { var T, k; if (this === null) { throw new TypeError(‘ this is null or not defined‘); } // 1. Let O be the result of calling toObject() passing the // |this| value as the argument. var O = Object(this); // 2. Let lenValue be the result of calling the Get() internal // method of O with the argument "length". // 3. Let len be toUint32(lenValue). var len = O.length >>> 0; // 4. If isCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 if (typeof callback !== "function") { throw new TypeError(callback + ‘ is not a function‘); } // 5. If thisArg was supplied, let T be thisArg; else let // T be undefined. if (arguments.length > 1) { T = thisArg; } // 6. Let k be 0 k = 0; // 7. Repeat, while k < len while (k < len) { var kValue; // a. Let Pk be ToString(k). // This is implicit for LHS operands of the in operator // b. Let kPresent be the result of calling the HasProperty // internal method of O with argument Pk. // This step can be combined with c // c. If kPresent is true, then if (k in O) { // i. Let kValue be the result of calling the Get internal // method of O with argument Pk. kValue = O[k]; // ii. Call the Call internal method of callback with T as // the this value and argument list containing kValue, k, and O. callback.call(T, kValue, k, O); } // d. Increase k by 1. k++; } // 8. return undefined };}
基本用法:
arr.forEach(callback[, thisArg]),callback会接收到三个参数:currentValue、index、array
var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"]; ary.forEach(function(value, index, _ary) { console.log(index + ": " + value); return false;});
// logs:
0: JavaScript
1: Java
2: CoffeeScript
3: TypeScript
使用some函数
var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"]; ary.some(function (value, index, _ary) { console.log(index + ": " + value); return value === "CoffeeScript";});
// logs:
0: JavaScript
1: Java
2: CoffeeScript
使用every函数
var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"]; ary.every(function(value, index, _ary) { console.log(index + ": " + value); return value.indexOf("Script") > -1;});
// logs:
0: JavaScript
1: Java
使用fo..of
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];for (let el of arr) { console.log(el); if (el === 5) { break; }}
// logs:
0
1
2
3
4
5
而如果forEach想实现类似every、some函数的效果该如何做呢?
在stackoverflow上得票比较高的有如下几类方法 :
1、循环外使用try.. catch,当需要中断时throw 一个异常,然后catch进行捕获;
2、重写forEach(也是借鉴第一种方法);
var BreakException = {}; try { [1, 2, 3].forEach(function(el) { console.log(el); if (el === 2) throw BreakException; });} catch (e) { if (e !== BreakException) throw e;}
// Use a closure to prevent the global namespace from be polluted.(function() { // Define StopIteration as part of the global scope if it // isn‘t already defined. if(typeof StopIteration == "undefined") { StopIteration = new Error("StopIteration"); } // The original version of Array.prototype.forEach. var oldForEach = Array.prototype.forEach; // If forEach actually exists, define forEach so you can // break out of it by throwing StopIteration. Allow // other errors will be thrown as normal. if(oldForEach) { Array.prototype.forEach = function() { try { oldForEach.apply(this, [].slice.call(arguments, 0)); } catch(e) { if(e !== StopIteration) { throw e; } } }; }})(); // Show the contents until you get to "2".[0,1,2,3,4].forEach(function(val) { if(val == 2) throw StopIteration; alert(val);});
参考链接:
http://dean.edwards.name/weblog/2006/07/enum/
http://www.jsnoob.com/2013/11/26/how-to-break-the-foreach/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
时间: 2024-12-24 20:13:42