JS 应用篇(三):JS中的遍历函数

2,219 阅读6分钟

在JS中的map()、filter()、forEach()、reduce()函数都是对数组内部的元素进行遍历,但是他们之间有什么区别呢?

一、Array.prototype.map()

1、说明

将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。

2、语法

var newArray = arr.map(function callback(currentValue, index, array){ 
    //对每个元素的处理 
}) 

// 参数
// currentValue:当前正在处理的元素 
// index:正在处理元素的索引 
// array:调用map方法的数组(就是.map()前面的,也就是arr)

3、示例

var arr = [1,2,3,4];
var newArr = arr.map(function(x){
    return x = x+1;
});
console.log(newArr , arr);
//newArr:2,3,4,5  
//arr:1,2,3,4

遍历数组中的每一个元素,然后对每一个元素执行函数中的处理,最后将返回值组成一个新的数组返回,原数组(arr)保持不变。

二、Array.prototype.forEach()

1、说明

对数组的所有成员依次执行参数函数。但是,forEach方法不返回值,只用来操作数据。

2、语法

var newArray = arr.forEach(function callback(currentValue, index , array){ 
    //函数代码 
}); 
// 参数 
// currentValue: 当前元素 
// index: 当前元素的索引 
// array:调用forEach的数组

3、示例

var arr = [1,2,3,4];
var newArr = arr.forEach(function(x){
    return x = x+1;
});
console.log(newArr , arr);
//newArr:undefined
//arr:1,2,3,4

遍历数组中的每一个元素,然后对每一个元素执行函数中的处理,没有返回值,即使设置了return也无效,原数组(arr)保持不变。而且一旦调用,会完全遍历一次,break, continue, return都无效。

三、Array.prototype.fliter()

1、说明

过滤数组成员,满足条件的成员组成一个新数组返回。

2、语法

var newArray = arr.filter(function callback(currentValue, index , array){ 
    //函数代码 
}); 
// 参数 
// currentValue: 当前元素 
// index: 当前元素的索引 
// array:调用filter的数组

3、示例

var arr = [1,2,3,4];
var newArr = arr.filter(function(x){
    return x > 1;
});
console.log(newArr , arr);
// newArr:2,3,4
// arr:1,2,3,4

遍历数组中的每一个元素,然后对每一个元素执行函数中的处理,最后判断返回值是否为true,将返回为true的数组元素(该元素为最原始的数组元素)组成一个新的数组返回,原数组(arr)保持不变。

四、Array.prototype.some()与Array.prototype.every()

1、说明

对数组的所有成员依次执行参数函数,返回一个布尔值。
some()是只要一个成员的返回值是true,则整个some()的返回值就是true,否则返回false。
every()是所有成员的返回值都是true,整个every()才返回true,否则返回false。

2、语法

var newArray = arr.some(function callback(currentValue, index , array){ 
    //函数代码 
}); 
// 参数 
// currentValue: 当前元素 
// index: 当前元素的索引 
// array:调用filter的数组

var newArray = arr.every(function callback(currentValue, index , array){ 
    //函数代码 
}); 
// 参数 
// currentValue: 当前元素 
// index: 当前元素的索引 
// array:调用filter的数组

3、示例

// 以some()为例:
var arr = [1,2,3,4];
var newArr = arr.some(function(x){
    return x > 1;
});
console.log(newArr , arr);
// newArr:true
// arr:1,2,3,4

遍历数组中的每一个元素,然后对每一个元素执行函数中的处理,最后判断返回值是否为true,
如果有一个成员返回值为true,则some()返回true,
如果所有成员返回值都为true,则every()返回true,
some()当内部return true时会提前跳出整个循环,every()当内部return false时会提前跳出整个循环,
原数组(arr)保持不变。

五、Array.prototype.reduce()

1、说明

使用函数依次处理数组的每个成员,最终累计为一个值。

2、语法

//语法 
var newArray = arr.reduce(callback(previousValue, currentValue, currentIndex,array){
    //函数代码 
},initialValue); 
//参数 
// previousValue: 上一次调用函数后的返回值,或者是提供的初始值(initialValue) 
// currentValue:当前数组的元素 
// currentIndex:当前数组元素的索引 
// array:调用reduce的数组 
// initialValue:初始值,作为第一次调用callback的第一个参数,也可不写,默认为0;

3、示例

var arr = [1,2,3,4];
var newArr = arr.reduce(function(total, current){
 return total + current;
},100);
console.log(newArr,arr);
// newArr:110
// arr:1,2,3,4

遍历数组中的每一个元素,然后对每一个元素执行函数中的处理,返回值会被记住,并且在遍历下一个元素中可以被调用,最后返回单个结果值,原数组(arr)保持不变。

六、for...in语句

1、说明

for-in 循环会遍历对象的属性名。

2、示例

const arr = [1, 2, 3];
let index;
for(index in arr) {
    console.log("arr[" + index + "] = " + arr[index]);
}
// arr[0] = 1
// arr[1] = 2
// arr[2] = 3

for-in 循环遍历的是对象的属性,遍历的对象不局限于数组,还可以遍历对象。并且不仅仅遍历对象自身的属性,其还遍历对象原型链上的所有可枚举的属性。
Array在JavaScript中是一个对象,它的索引就是属性名,并且Array的索引也不是Number类型,而是String类型(我们之所以能够使用array[0]的原因是JS自动将Number类型的0转换我饿String类型。)
注意:for-in 遍历属性的顺序并不确定,即输出的结果顺序与属性在对象中的顺序无关,也与属性的字母顺序无关,与其他任何顺序也无关。

七、for...of语句

1、说明

由于之前的forEach与for...in存在的诸多缺陷:

  • forEach 不能 break 和 return;
  • for-in 缺点更加明显,它不仅遍历数组中的元素,还会遍历自定义的属性,甚至原型链上的属性都被访问到。而且,遍历数组元素的顺序可能是随机的。

在ES6中新增了新的循环语法for...of,for...of能够直接从遍历中取值。

2、示例

const arr = ['a', 'b', 'c'];
for(let data of arr) {
    console.log(data);
}
// a
// b
// c
  • 跟 forEach 相比,可以正确响应 break, continue, return。
  • for-of 循环不仅支持数组,还支持大多数类数组对象,例如 DOM nodelist 对象。
  • for-of 循环也支持字符串遍历,它将字符串视为一系列 Unicode 字符来进行遍历。
  • for-of 也支持 Map 和 Set (两者均为 ES6 中新增的类型)对象遍历。

注意:for-of循环不支持普通对象。

八、区别总结

以上介绍的这些方法都是依次使用函数处理数组中的每一个成员,但是都有细微的差别,下面将整理各个函数中的差别。

map(): 在处理函数中将返回值组成一个新的数组返回,原数组(arr)保持不变。

forEach(): 没有返回值,即使处理函数中设置了return也无效,原数组(arr)保持不变。而且一旦调用,会完全遍历一次,break, continue, return都无效。

filter(): 判断处理函数中的返回值是否为true,将返回为true的数组元素(该元素为最原始的数组元素)组成一个新的数组返回,原数组(arr)保持不变。

some()与every(): 判断处理函数中的返回值是否为true,如果有一个成员返回值为true,则some()返回true;如果所有成员返回值都为true,则every()返回true,原数组(arr)保持不变。

reduce(): 返回值会被记住,并且在遍历下一个元素中可以被调用,最后返回单个结果值,原数组(arr)保持不变。

for...in: 循环遍历的是对象的属性名,遍历的对象不局限于数组,还可以遍历对象。并且不仅仅遍历对象自身的属性,其还遍历对象原型链上的所有可枚举的属性。

for...of: 循环遍历数组的值,不仅支持数组,还支持大多数类数组对象,但是不支持遍历普通对象。

参考资料:
.map()和.filter()以及他们的区别
网道-Array
MDN-Array