forEach
forEach是Array新方法中最基本的一个,就是遍历,循环。例如下面这个例子:
1
|
[1, 2 ,3, 4].forEach(alert);
|
等同于下面这个传统的for循环:
1
2
3
4
5
|
var array = [1, 2, 3, 4];
for (var k = 0, length = array.length; k < length; k++) {
alert(array[k]);
}
|
Array在ES5新增的方法中,参数都是function类型,默认有传参,这些参数分别是?见下面:
1
2
3
4
5
6
7
8
9
|
[1, 2 ,3, 4].forEach(console.log);
// 结果:
// 1, 0, [1, 2, 3, 4]
// 2, 1, [1, 2, 3, 4]
// 3, 2, [1, 2, 3, 4]
// 4, 3, [1, 2, 3, 4]
<span style= "font-family: Arial, Verdana, sans-serif;" >显而易见,forEach方法中的 function 回调支持3个参数,第1个是遍历的数组内容;第2个是对应的数组索引,第3个是数组本身。</span>
|
因此,我们有:
1
2
3
|
[].forEach( function (value, index , array) {
// ...
});
|
对比jQuery中的$.each方法:
1
2
3
|
$.each([], function ( index , value, array) {
// ...
});
|
会发现,第1个和第2个参数正好是相反的,大家要注意了,不要记错了。后面类似的方法,例如$.map也是如此。
现在,我们就可以使用forEach卖弄一个稍显完整的例子了,数组求和:
1
2
3
4
5
6
7
8
|
var sum = 0;
[1, 2, 3, 4].forEach( function (item, index , array) {
console.log(array[ index ] == item); // true
sum += item;
});
alert( sum ); // 10
|
再下面,更进一步,forEach除了接受一个必须的回调函数参数,还可以接受一个可选的上下文参数(改变回调函数里面的this指向)(第2个参数)。
1
|
array.forEach(callback,[ thisObject])
|
例子更能说明一切:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
var database = {
users: [ "张含韵" , "江一燕" , "李小璐" ],
sendEmail: function ( user ) {
if (this.isValidUser( user )) {
console.log( "你好," + user );
} else {
console.log( "抱歉," + user + ",你不是本家人" );
}
},
isValidUser: function ( user ) {
return /^张/.test( user );
}
};
// 给每个人法邮件
database .users.forEach( // database .users中人遍历
database .sendEmail, // 发送邮件
database // 使用 database 代替上面标红的this
);
// 结果:
// 你好,张含韵
// 抱歉,江一燕,你不是本家人
// 抱歉,李小璐,你不是本家
|
如果这第2个可选参数不指定,则使用全局对象代替(在
浏览器
是为window),严格模式下甚至是undefined.
另外,forEach不会遍历纯粹“占着官位吃空饷”的元素的,例如下面这个例子:
1
2
3
4
5
6
7
8
|
var array = [1, 2, 3];
delete array[1]; // 移除 2
alert(array); // "1,,3"
alert(array.length); // but the length is still 3
array.forEach(alert); // 弹出的仅仅是1和3
|
综上全部规则,我们就可以对IE6-IE8进行仿真扩展了,如下代码:
1
2
3
4
5
6
7
8
9
10
11
|
// 对于古董浏览器,如IE6-IE8
if (typeof Array.prototype.forEach != "function" ) {
Array.prototype.forEach = function (fn, context) {
for (var k = 0, length = this.length; k < length; k++) {
if (typeof fn === "function" && Object.prototype.hasOwnProperty.call(this, k)) {
fn.call(context, this[k], k, this);
}
}
};
}
|