转载地址:https://www.zhangxinxu.com/wordpress/2013/04/es5%e6%96%b0%e5%a2%9e%e6%95%b0%e7%bb%84%e6%96%b9%e6%b3%95/
一、前言-索引
ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for
循环了。
ES5中新增了写数组方法,如下:
- forEach (js v1.6)
- map (js v1.6)
- filter (js v1.6)
- some (js v1.6)
- every (js v1.6)
- indexOf (js v1.6)
- lastIndexOf (js v1.6)
- reduce (js v1.8)
- reduceRight (js v1.8)
浏览器支持
- Opera 11+
- Firefox 3.6+
- Safari 5+
- Chrome 8+
- Internet Explorer 9+
对于让人失望很多次的IE6-IE8浏览器,Array原型扩展可以实现以上全部功能,例如forEach
方法:
// 对于古董浏览器,如IE6-IE8 if (typeof Array.prototype.forEach != "function") { Array.prototype.forEach = function () { /* 实现 */ }; }
二、一个一个来
- forEach
forEach
是Array新方法中最基本的一个,就是遍历,循环。例如下面这个例子:[1, 2 ,3, 4].forEach(alert);
等同于下面这个传统的
for
循环: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].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]
显而易见,
forEach
方法中的function
回调支持3个参数,第1个是遍历的数组内容;第2个是对应的数组索引,第3个是数组本身。因此,我们有:
[].forEach(function(value, index, array) { // ... });
对比jQuery中的
$.each
方法:$.each([], function(index, value, array) { // ... });
会发现,第1个和第2个参数正好是相反的,大家要注意了,不要记错了。后面类似的方法,例如
$.map
也是如此。现在,我们就可以使用
forEach
卖弄一个稍显完整的例子了,数组求和: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个参数)。array.forEach(callback,[ thisObject])
例子更能说明一切:
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不会遍历纯粹“占着官位吃空饷”的元素的,例如下面这个例子:
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进行仿真扩展了,如下代码:
// 对于古董浏览器,如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); } } }; }
现在拿上面“张含韵”的例子测下我们扩展的
forEach
方法,您可能狠狠地点击这里:兼容处理的forEach方法demo例如IE7浏览器下: