遍历数组的方法有很多种,传统的有:for、forEach、for-in、 for-of(ES6),其他的还有:map、reduce、reduceRight、filter、every、some、find(ES6)、findIndex(ES6)
传统经典
for
适用于数组和字符串
let arrOrStr = [1, 2, 3, 4, 5, 6];
// let arrOrStr = 'abcdefg';
for(let i = 0, len = arrOrStr.length; i < len; i++){
console.log(arrOrStr[i])
}
forEach
- 适用于数组,对数组的每个元素执行一次 callback 函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)。
- 返回 undefined 值,并且不可链式调用。
- forEach() 遍历的范围在第一次调用 callback 前就会确定。
- forEach() 被调用时,不会改变原数组,但 callback 函数在被调用时可能会改变原数组。
- 注意: 除了抛出异常以外,没有办法中止或跳出 forEach() 循环。
let items = ['1', '2', '3'];
let copy = [];
items.forEach((item) => {
copy.push(item);
})
扁平化数组
function flatten(arr) {
const result = [];
arr.forEach((i) => {
if (Array.isArray(i))
result.push(...flatten(i));
else
result.push(i);
})
return result;
}
const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]];
flatten(problem); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
for in
- 建议用于遍历对象,不建议用于数组,以任意顺序迭代对象的除Symbol以外的可枚举属性。
- 可以由 break, throw continue 或 return 终止。
- 被调用时迭代传入对象的所有可枚举属性,然后返回一个所有属性名和其对应值的字符串:
var obj = {a: 1, b: 2, c: 3};
for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
}
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
for of
- 适用于可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等),在迭代对象上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。
- 可以由break, throw continue 或return终止。
let iterable = "boo";
for (let value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"
for in 和 for of 的区别
for…in 语句以任意顺序迭代对象的除Symbol以外的可枚举属性,会把继承自父类的属性也遍历一遍,所以会更花时间。
for…of 语句遍历可迭代对象定义要迭代的数据。
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
let iterable = [3, 5, 7];
iterable.foo = 'hello';
for (let i in iterable) {
console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}
for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // logs 0, 1, 2, "foo"
}
}
for (let i of iterable) {
console.log(i); // logs 3, 5, 7
}
其他循环方法
map
map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次 callback(currentValue, index, array) 函数后的返回值。
var kvArray = [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}];
var reformattedArray = kvArray.map(function(obj) {
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray 数组为: [{1: 10}, {2: 20}, {3: 30}]
reduce
- reduce() 方法对数组中的每个元素执行 callback 函数(升序执行),将其结果汇总为单个返回值。
- 接收除 callback 外的可选参数 initialValue ,作为第一次调用 callback 函数时的第一个参数的值。如果没有提供,则将使用数组中的第一个元素。在没有初始值的空数组上调用 reduce 将报错。
- 注意: reduce() 对于空数组是不会执行回调函数的。
- callback 函数接收四个参数:
- accumulator (acc) (累计器):累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue
- currentValue (cur) (当前值):数组中正在处理的元素
- currentIndex (idx) (当前索引):数组中正在处理的当前元素的索引。如果提供了initialValue,则起始索引号为0,否则从索引1起始
- sourceArray (src) (源数组):调用reduce()的数组
accumulator 和 currentValue 的取值有两种情况:
- 如果调用 reduce() 时提供了 initialValue,accumulator 取值为 initialValue,currentValue 取数组中的第一个值;
- 如果没有提供 initialValue,那么 accumulator 取数组中的第一个值,currentValue 取数组中的第二个值。
MDN例子
reduceRight() 用法与 reduce 相同,只是执行 callback 函数的顺序是降序(从右往左)。
filter
- filter() 方法创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
- 注意: filter() 不会对空数组进行检测。
const fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];
const filterItems = (query) => {
return fruits.filter((el) =>
el.toLowerCase().indexOf(query.toLowerCase()) > -1 // ES6箭头函数中只有一句代码且为return时,可以省略return
);
}
console.log(filterItems('ap')); // ['apple', 'grapes']
console.log(filterItems('an')); // ['banana', 'mango', 'orange']
every
- every() 方法测试一个数组内的所有元素是否都能通过 callback 函数的测试,返回一个布尔值。
- 如果回调函数的每一次返回都为 truthy 值,返回 true ,否则返回 false。
- 注意: 若用一个空数组测试,此方法在一切情况下都会返回 true。
[12, 5, 8, 130, 44].every(x => x >= 10); // false
[12, 54, 18, 130, 44].every(x => x >= 10); // true
some
- some() 方法测试数组中是不是至少有1个元素通过了 callback 函数测试,返回一个布尔值。
- 注意: 若用一个空数组测试,在任何情况下它返回的都是false。
[2, 5, 8, 1, 4].some(x => x > 10); // false
[12, 5, 8, 1, 4].some(x => x > 10); // true
find
find() 方法返回数组中满足 callback 函数的第一个元素的【值】。否则返回 undefined。
var inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
function findCherries(fruit) {
return fruit.name === 'cherries';
}
console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
findIndex() 方法的用法同 find,只是返回的是第一个满足条件的元素的下标