JavaScript 为数组定义了多个具有迭代功能的方法,如 forEach、filter、map、every、some。本节练习使用 JavaScript 设计自己的迭代器。
迭代器(Iterator)提供了一种对数据集合中每个元素执行重复操作的机制,通常与循环结构配合使用,因此也称为循环器。它能够根据传递的函数型参数为集合中每个元素反复执行相同的命令,直到满足某些条件为止。迭代器通常用于迭代数组的值,或者执行重复的任务。
Array.prototype.each = function (f) { //数组迭代器,扩展Array原型反复
try{ //异常处理,避免不可预测的错误
this.i || (this.i = 0); //初始化迭代计数器
if (this.length > 0 && f.constructor == Function) { //如果数组长度大于0,参数为函数
while (this.i < this.length) { //遍历数组
var e = this[this.i]; //获取当前元素
if (e && e.constructor == Array) { //如果元素存在,切为数组
e.each(f); //递归调用迭代器
} else { //否则,在元素上调用参数函数,并传递值
f.apply(e, [e]);
}
this.i ++; //递加计数器
}
this.i = null; //如果遍历完毕,则清空计数器
}
}catch(w) { //捕获异常,暂不处理
return this; //返回当前数组
}
}
var a = [1, [2, [3,4]]];
var f = function (x) {
console.log(x);
}
a.each(f); //调用迭代器,为每个元素执行一次函数传递
不能使用 for/in 语句进行循环操作,因为 for/in 能够迭代本地属性。
动态改变数组中每个元素的值。
Array.prototype._edit = Array.prototype.edit || (Array.prototype.edit = function () { //数组元素批处理方法
var b = arguments, a = []; //获取参数,并定义一个临时数组
this.each (function () { //调用迭代器,遍历所有元素
a.push(b[0].call(b[1], this)); //调用参数函数,把当前元素作为参数传入
});
return a; //返回临时数组
});
Object.prototype.edit = Array.prototype._edit;
为 Array 对象定义了一个原型方法 edit(),该方法能够根据参数函数编辑数组中每个元素,并返回这个编辑后的数组。
在这个原型方法中,首先定义临时变量获取 edit() 方法的参数,并定义一个临时数组,用来存储编辑后的数组元素值。然后调用迭代器 each(),遍历数组中所有元素,为迭代器传递一个参数,该函数将在每个元素上执行。在该函数中包含一句处理语句,它通过 call() 方法调用传递给 edit() 的参数函数,并把当前元素作为参数传递给该参数函数进行执行,执行结果被推进临时数组 a 中,最后返回这个临时的数组 a。
var a = [1,2,3,4]; //定义数组直接量
var f = function (x) { //求平方值
return x * x;
}
var b = a.edit(f); //为数组元素执行求平方操作
console.log(b); //返回[1,4,9,16]
在处理多维数组时,该原型方法会把它们全部转换为一维数组。
过滤数组元素。
Array.prototype._filter = Array.prototype.filter || (Array.prototype.filter = function () {
var b = arguments, a = [];
this.each(function () {
if (b[0].call(b[1], this))
a.push(this);
});
return a;
});
Object.prototype.filter = Array.prototype._filter;
定义一个过滤函数,对每个元素进行检测。如果满足条件,则返回 true,否则返回 false。最后把过滤函数传递给迭代器,即可达到过滤数组元素的目的。
定义数组和一个过滤函数,设计如果参数值大于 4,则返回 true。
var a = [1,2,3,4,5,6,7,8,9];
var f = function (x) {
if (x > 4) return true;
}
调用数组 a 的原型方法 filter(),并把过滤函数作为参数传递给方法 filter()。
var b = a.filter(f); //调用数组元素过滤方法
console.log(b); //返回[5,6,7,8,9]