Array.prototype.map()
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map() 不会改变原始数组。
举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个数组[1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map实现如下:
由于map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个新的Array作为结果:
function pow(x) {
return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
//map()传入的参数是pow,即函数对象本身。
你可能会想,不需要map(),写一个循环,也可以计算出结果:
var f = function (x) {
return x * x;
};
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [];
for (var i=0; i<arr.length; i++) {
result.push(f(arr[i]));
}
的确可以,但是,从上面的循环代码,我们无法一眼看明白“把f(x)作用在Array的每一个元素并把结果生成一个新的Array”。
所以,map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把Array的所有数字转为字符串:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']
只需要一行代码。
Array.prototype.reduce()
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
注意: reduce() 对于空数组是不会执行回调函数的。
很多时候需要累加数组项的得到一个值(比如说求和)。如果你碰到一个类似的问题,你想到的方法是什么呢?会不会和我一样,想到的就是使用for或while循环,对数组进行迭代,依次将他们的值加起来。比如:
var arr = [1,2,3,4,5,6];
Array.prototype.sum = function(){
var result = 0;
for(var i = 0; i < this.length; i++){
resule += parseInt(this[i]);
}
return result;
}
arr.sum();//21
或者
var arr = [1,2,3,4,5,6];
Array.prototype.sum = function(){
var result = 0;
var i = this.length;
while(i--){
result += parseInt(this[i]);
}
return result;
}
arr.sum();//21
那他们是不是最好的方案呢?先看看他们所耗的时间。
// 测试for和while循环实现数组求和的性能
var arr = [1,2,3,4,5,6];
// for循环
console.time("forLoop");
Array.prototype.forLoop = function (){
for (var i = 0; i < 10000; i++) {
var sumResult = 0;
for (var j = 0; j < this.length; j++) {
sumResult += parseInt(this[j]);
}
}
return sumResult;
}
arr.forLoop();
console.log('最终的值:' + arr.forLoop()); // 21
console.timeEnd("forLoop"); // 54.965ms
再来看看while循环所用时间:
var arry = [1,2,3,4,5,6];
console.time("whileLoop");
Array.prototype.whileLoop = function () {
for (var i = 0; i < 10000; i++) {
var sumResult = 0;
for (var j = 0; j < this.length; j++) {
sumResult += parseInt(this[j]);
}
}
return sumResult;
}
arry.whileLoop();
console.log('最终的值:' + arry.whileLoop()); // 21
console.timeEnd("whileLoop"); // 53.056ms
备注:数组[1,2,3,4,5,6]做了10000次循环的累加。
虽然上面使用for和while都能实现需要的效果,但在JavaScript中有没有更好的方案呢?回答是肯定的,在JavaScript中(ESMAScript 5)提供了另外两个数组的方法reduce()和reduceRight(),这两个数组会迭代数组的所有数组项,然后返回一个最终值。接下来的内容,主要来学习这两种方法。
function callbackfn(preValue,curValue,index,array){}
preValue: 上一次调用回调返回的值,或者是提供的初始值(initialValue)
curValue: 数组中当前被处理的数组项
index: 当前数组项在数组中的索引值
array: 调用 reduce()方法的数组
回调函数第一次执行时,preValue 和 curValue 可以是一个值,如果 initialValue 在调用 reduce() 时被提供,那么第一个 preValue 等于 initialValue ,并且curValue 等于数组中的第一个值;如果initialValue 未被提供,那么preValue 等于数组中的第一个值,`curValue等于数组中的第二个值。
再来看一个示例:
var arr = [0,1,2,3,4]; arr.reduce(function (preValue,curValue,index,array) { return preValue + curValue; }); // 10
最后看下耗费时间对比:
最后的补充
最后想补充两个我平时没有注意,但是很好用的函数。
fill()方法:使用固定的值填充数组。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.fill("Runoob");
var arr = new Array(4);
arr.fill(1);
//arr=[1,1,1,1]
filter():方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
注意: filter() 不会对空数组进行检测。
注意: filter() 不会改变原始数组。
var arr = [1,2,3,4,5];
arr.filter(function(item){return item>2});