在JavaScript中遍历数组通常使用for循环。
自从ES5发布之后也可以使用forEach。如果使用forEach遍历数组的话,使用break不能中断循环,使用return也不能返回到外层函数。
在ES5中具有遍历数组功能的还有map()、filter()、some()、every()、reduce()、reduceRight()等。
因此另外有for-in循环和for-of循环两种增强型循环。其中,for-in是ES5标准,遍历的是key(可遍历对象、数组或字符串的key)。
for-of是ES6标准,遍历的是value(可遍历对象、数组或字符串的value)。
for-in
for…in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。
let arr = ['我','是','南','栀'];
for(let index in arr){
console.log(index,arr[index]);
}
输出结果:
使用for-in遍历数组出现的问题:
- index索引为字符串数字(注意:非数字),不能直接进行集合运算。
- 遍历顺序有可能不是按照实际数组的内部顺序(可能按照随机顺序)。
- 使用for-in会遍历数组的所有可枚举属性,包括原型。例如上例的原型方法method和name属性都会被遍历出来,通常需要配合hasOwnProperty()方法判断某个属性是否该对象的实例属性,来将原型对象从循环中剔除。
Object.prototype.objCustom = function(){};
Array.prototype.arrCustom = function(){};
let arr = [3,5,7];
arr.foo = 'hello';
console.log(arr); // [ 3, 5, 7, foo: 'hello' ]
/**
* 输出:
* 0
* 1
* 2
* foo
* arrCustom
* objCustom
*/
for(let index in arr){
console.log(index);
}
/**
* 输出:
* 0
* 1
* 2
* foo
*/
for(let index in arr){
if(arr.hasOwnProperty(index)){
console.log(index);
}
}
for-of
for…of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。
for-of可以简单、正确地遍历数组(不遍历原型method和name)。
与forEach()不同的是,它可以正确响应break、continue和return语句。
Object.prototype.objCustom = function(){};
Array.prototype.arrCustom = function(){};
let arr = [3,5,7];
arr.foo = 'hello';
console.log(arr); // [ 3, 5, 7, foo: 'hello' ]
/**
* 输出:
* 3
* 5
* 7
*/
for(let index of arr){
console.log(index);
}
forEach
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
注意: forEach() 对于空数组是不会执行回调函数的。
array.forEach(function(currentValue, index, arr){})
:
- currentValue:必需。当前元素。
- index:可选。当前元素索引值
- arr:可选。当前元素所属的对象数组。
let sum = 0;
var arr = [1,2,3,4];
arr.forEach(function(value,index,array){
array[index] == value; //结果为true
sum+=value;
});
console.log(sum); //结果为 10
forEach() 本身是不支持的 continue 与 break 语句的。
continue的实现:
var arr = [1, 2, 3, 4, 5];
arr.forEach(function (item) {
if (item === 3) {
return; // 不能为return false;
}
console.log(item);
});
break的实现:
var arr = [1, 2, 3, 4, 5];
arr.every(function (item) {
console.log(item);
return item !== 3;
});
forEach()与map()的区别
forEach()
: 针对每一个元素执行提供的函数callback可以改变原始数组的元素。map()
: 创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来。
forEach()方法不会返回执行结果,而是undefined。
也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
执行速度对比:
forEach()的执行速度比map()慢了70%。
适用场合:
forEach
:适合于你并不打算改变数据的时候,而只是想用数据做一些事情 – 比如存入数据库或则打印出来。
let arr = ['a', 'b', 'c', 'd'];
arr.forEach((letter) => {
console.log(letter);
});
// a
// b
// c
// d
map()
:适用于你要改变数据值的时候。不仅仅在于它更快,而且返回一个新的数组。这样的优点在于你可以使用 filter(), reduce()等组合进行使用。
let arr = [1, 2, 3, 4, 5];
let arr2 = arr.map(num => num * 2).filter(num => num > 5);
// arr2 = [6, 8, 10]