一、ECMA5中新增了forEach()方法
JavaScript诞生已经有20多年了,我们一直使用的用来循环一个数组首先想到的当然是for(var i=0;i<count;i++),在ECMA5中新增了forEach()方法。因为forEach()方法是ECMAscript5增加的方法,IE8以下(包括IE8)浏览器不完全支持ES5。写法简单了许多,但也有短处:你不能中断循环(使用break
语句或使用return
语句,这个之后实现中断或跳出循环)。
语法:array1.forEach(callbackfn[, thisArg])
参数 |
定义 |
---|---|
array1 |
必选。一个数组对象。 |
callbackfn |
必选。最多可以接受三个参数的函数。对于数组中的每个元素,forEach 都会调用 callbackfn 函数一次。 |
thisArg |
可选。 callbackfn 函数中的 this 关键字可引用的对象。如果省略 thisArg,则 undefined 将用作 this 值。 |
异常:如果 callbackfn 参数不是函数对象,则将引发 TypeError 异常。
1、1:原生写法
[].forEach(function(value, index, array) { // ... });
例如:
var arr = [1,2,3,4]; arr.forEach(function(value,index,array){ console.info("index:"+index+" value: "+value); });
结果输出为:
"index:0 value: 1" "index:1 value: 2" "index:2 value: 3" "index:3 value: 4"
1、2:jQuery方式
$.each([], function(index, value, array) { // ... });
1.3:map映射模式
[].map(function(value,index,array){ //code })
二、forEach()方法兼容与实现
2、1:因为forEach()方法是ECMAscript5增加的方法,IE8以下(包括IE8)浏览器不完全支持ES5,这里给出了一个IE兼容模式
if (!Array.prototype.forEach) { Array.prototype.forEach = function(callback, thisArg) { var T, k; if (this == null) { throw new TypeError("this is null or not defined"); } var O = Object(this); var len = O.length >>> 0; // Hack to convert O.length to a UInt32 if ({}.toString.call(callback) != "[object Function]") { throw new TypeError(callback + " is not a function"); } if (thisArg) { T = thisArg; } k = 0; while (k < len) { var kValue; if (k in O) { kValue = O[k]; callback.call(T, kValue, k, O); } k++; } }; }
在IE8环境中贴出代码
var arr = []; arr.push(1); arr.push(2); arr.push(3); arr.push(4); arr.forEach(function(value,index,array){ alert("index:"+index+" value: "+value); });
输出结果:
"index:0 value: 1" "index:1 value: 2" "index:2 value: 3" "index:3 value: 4"
三、如何中断forEach()方法
由于之前说到一个问题,如何在forEach里实现break,目前有几种方案
3、1:throw法抛出一个错误,但是需要注意的是要抛出一个可以与别的错误区别开的错误,这样不会干扰别的代码抛出的错误
var BreakException = {}; try { [1, 2, 3].forEach(function(v) { console.log(v); //只输出1,2 if (v === 2) throw BreakException; }); } catch (e) { if (e !== BreakException) throw e; } //结果 1 2
3、2:空循环,在外层加一个标识,如果此标识为true,接下来的循环空跑
[1, 2, 3].forEach(function(v) { if (this.breakFlag === true) { return false; } if (v === 2) { this.breakFlag = true } console.log(v) //只输出1,2 });
3、3:修改数组
var array = [1, 2, 3, 4, 5]; array.forEach(function(item, index) { if (item === 2) { array = array.concat(array.splice(index, array.length - index)); } console.log(item); //只输出1,2 });
3、4:使用的every:需要break
的场景下,直接使用every
或者some.
every: 碰到return false的时候,循环中止
some: 碰到return ture的时候,循环中止
var a = [1, 2, 3, 4, 5] a.every(function(item, index, arry) { console.log(item); //返回1,2 if (item === 2) { return false } else { return true } }); var a = [1, 2, 3, 4, 5] a.some(function(item, index, arry) { console.log(item); //返回1,2 if (item === 2) { return true } else { return false } })
四、总结
4、1:for-in
JavaScript里还有一种循环方法:for
–in.该循环实际是为循环"
enumerable
"对象而设计的,所以不推荐用for-in来循环一个数组,因为,不像对象,数组的index
跟普通的对象属性不一样,是重要的数值序列指标。
var obj = {a:1, b:2, c:3}; for (var prop in obj) { console.log("obj." + prop + " = " + obj[prop]); } // 输出: // "obj.a = 1" // "obj.b = 2" // "obj.c = 3"
总之,for
–in
是用来循环带有字符串key的对象的方法。
4.2:参考
https://msdn.microsoft.com/zh-cn/library/ff679980(v=vs.94).aspx