JS常用的循环遍历
for、forEach、for …of for…in
-
for
通常用于数组的循环 可以随时跳出循环,用break或者continue
const list = [1, 2, 3, 4, 5, 6, 7, 8, , 10, 11]; let len = list.length; for (let i = 0; i < len; i++) { if (list[i] === 5) { // break; // 1 2 3 4 continue; // 1 2 3 4 6 7 8 undefined 10 11 } console.log(list[i]); }
-
forEach
可以对循环的元素做一些特定的操作,回调函数的参数更丰富,元素,索引和原数组都可以获得。
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
注意: forEach() 对于空数组是不会执行回调函数的。
回调函数的语法如下:
array.forEach(function(currentValue, index, arr), thisValue)
其中 第一个参数为回调函数
function(currentValue, index, arr)
,currentValue 是必须的,表示当前的正在遍历的元素,index和arr是可选的,分别表示当前元素的索引以及当前元素所属的数组对象第二个参数thisValue是可选的,传递给函数的值一般用
this
值,如果这个参数为空,undefined
,会传递给this
值const list = [1, 2, 3, 4, 5, 6, 7, 8, , 10, 11]; let len = list.length; let result = [] list.forEach(function(cur,index,arr){ console.log(`当前元素为${cur},索引为${index},所属数组为${arr}`); result.push(cur*2); }) console.log(result); //[ 2, 4, 6, 8, 10, 12, 14, 16, 20, 22] let rest = [] rest.forEach(function(cur){ console.log("我没有执行啊~~,因为我是空数组"); })
注意:
forEach 无法跳出循环
,一旦执行了,除非抛出错误,否则会一直执行下去,直到数组的最后一个元素。不支持 continue,用 return false 或 return true 代替。
var arr = [1, 2, 3, 4, 5]; arr.forEach(function (item) { if (item === 3) { return; } console.log(item); //1 2 4 5 });
不支持 break,用 try catch/every/some 代替:
返回值: undefined
const list = [1,2,3,4] const result = list.forEach(function(cur){ return cur }) console.log(result); //undefined
-
for in
-
获取enumerable:true的属性键。
-
可以遍历对象(这时候获得是对象的键)和数组(数组的索引)。
-
可以获取原型上的属性键。
-
数字属性键被遍历出来是字符串。比如索引值
-
不可以跳出循环
const list = [1, 2, 3, 4, 5, 6, 7, 8, , 10, 11]; let len = list.length; //1. 对于数组 for(const k in list){ // console.log(k); //[0,1,2,3,4,5,6,7,8,9,10] //k 是索引 console.log(list[k]); //[1,2,3,4,5,6,7,8,10,11] //忽略空元素 if(k===5){ //不会退出 break; } } Object.prototype.fun = () => {}; const obj = { 2: 'a', 1: 'b' }; for (const i in obj) { console.log(i, ':', obj[i]); } // 1: b // 2: a // fun : () => {} Object 原型链上扩展的方法也被遍历出来 for (const i in obj) { if (Object.prototype.hasOwnProperty.call(obj, i)) { console.log(i, ':', obj[i]); } } //1 : b //2 : a // fun不属于自身的属性将被 hasOwnProperty 过滤
注意:
使用 for in 循环时,返回的是所有能够通过对象访问的、可枚举的属性,
既包括存在于实例中的属性,也包括存在于原型中的实例。如果只需要获取对象的实例属性,可以使用 hasOwnProperty 进行过滤
。使用时,要使用
(const x in a)
而不是(x in a)
后者将会创建一个全局变量。遍历的顺序会因为浏览器的不同而不同
-
-
for of:
-
遍历属性值。不受到enumerable限制。
-
可遍历数组。一般不可以遍历对象,如果实现了Symbol.iterator,可以遍历。如Array,Map,Set,String,TypedArray,arguments 对象等等
-
不能获取原型上的值
-
可以用break退出循环和continue跳过循环
-
for …of 直接访问的是实际元素
-
如果遇到空元素同样会执行
const list = [1, 2, 3, 4, 5, 6, 7, 8, , 10, 11]; let len = list.length; //1. 对于数组 for(const v of list){ // console.log(v); //[1,2,3,4,5,6,7,8,undefined,10,11] //v 是元素的值 不会忽略空元素 if(v === 7) break; //允许退出 continue也有有效 console.log(v);//[1,2,3,4,5,6] } // 2 对于对象 // 原型上增加方法 Array.prototype.gogo = function(){ console.log("gogo"); } var a = [1,2,3]; // key值2不可以枚举 Object.defineProperty(a, 2, { enumerable: false }); Object.defineProperty(a, "2", { enumerable: false }); for(let p in a){ // 索引被遍历出来是字符串类型 console.log(p, typeof p); // 0 string; 1 string; gogo string } console.log("---") for(let v of a){ console.log(v); // 1 2 3 }
-
some every
-
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
some() 方法会依次执行数组的每个元素:
- 如果有一个元素满足条件,则表达式返回true ,
剩余的元素不会再执行检测
。 - 如果没有满足条件的元素,则返回false。
注意:
some() 不会对空数组进行检测
。注意:
some() 不会改变原始数组
。some语法:
array.some(function(currentValue,index,arr),thisValue)
和forEach类似
注意:
返回值: 布尔值。如果数组中有元素满足条件返回 true,否则返回 false。
const list = [ { name: '头部导航', backward: false }, { name: '轮播', backward: true }, { name: '页脚', backward: false }, ]; const someBackward = list.some(item => item.backward); console.log(someBackward);//true const arr = [1,2,3,4] const result =arr.some(function(item){ if(item===5) return true; }) console.log(result); //false
- 如果有一个元素满足条件,则表达式返回true ,
-
every
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every() 方法使用指定函数检测数组中的所有元素:
- 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
- 如果所有元素都满足条件,则返回 true。
注意:
every() 不会对空数组进行检测
。注意:
every() 不会改变原始数组
。返回值:布尔值。如果所有元素都通过检测返回 true,否则返回 false。
const list = [
{ name: '头部导航', backward: false },
{ name: '轮播', backward: true },
{ name: '页脚', backward: false },
];
const everyNewest = list.every(item => !item.backward);
console.log(everyNewest); //false
const arr = [1,2,3,4]
const result =arr.every(function(item){
if(item>3) return true;
})
console.log(result); //false
const result2 =arr.every(function(item){
if(item<5) return true;
})
console.log(result2); //true
比较
- 二者都是用来做数组条件判断的,都是返回一个布尔值。
- 二者都可以被中断。
- some 若某一元素满足条件,返回 true,循环中断。所有元素不满足条件,返回 false。
- every 与 some 相反,若有一元素不满足条件,返回 false,循环中断。所有元素满足条件,返回 true。
filter、map
-
filter
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
注意: filter() 不会对空数组进行检测。
注意: filter() 不会改变原始数组。
语法:
array.filter(function(currentValue,index,arr), thisValue)
与forEach类似返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组。
-
map
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map() 不会改变原始数组。
语法:
array.map(function(currentValue,index,arr), thisValue)
**返回值:**返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
比较:
- 二者都是生成一个新数组,都不会改变原数组(不包括遍历对象数组时,在回调函数中操作元素对象)。
- 二者都会跳过空元素。
- map 会将回调函数的返回值组成一个新数组,
数组长度与原数组一致
。 - filter 会将符合回调函数条件的元素组成一个新数组。
- map 生成的新数组元素可自定义。
- filter 生成的新数组元素不可自定义,与对应原数组元素一致。
const list = [
{ name: '头部导航', type: 'nav', id: 1 },
,
{ name: '轮播', type: 'content', id: 2 },
{ name: '页脚', type: 'nav', id: 3 },
];
const resultList = list.filter(item => {
return item.type === 'nav';
});
console.log(resultList); //跳过空元素
//输出:
//[
// { name: '头部导航', type: 'nav', id: 1 },
// { name: '页脚', type: 'nav', id: 3 },
// ]
const newList = list.map(item => {
console.log(item);
return item.id;
});
console.log(newList); //[1, , 2, 3] //跳过空元素
find、findIndex
-
find
find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。
find() 方法为数组中的每个元素都调用一次函数执行:
- 当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,
之后的值不会再调用执行函数。
(找到就停止) - 如果没有符合条件的元素返回 undefined
注意: find() 对于空数组,函数是不会执行的。
注意: find() 并没有改变数组的原始值。
语法:
array.find(function(currentValue, index, arr),thisValue)
返回值:返回符合测试条件的第一个数组元素值,如果没有符合条件的则返回 undefined。
- 当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,
-
findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
findIndex() 方法为数组中的每个元素都调用一次函数执行:
- 当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。
- 如果没有符合条件的元素返回 -1
注意: findIndex() 对于空数组,函数是不会执行的。
注意: findIndex() 并没有改变数组的原始值。
语法:
array.findIndex(function(currentValue, index, arr), thisValue)
返回值:返回符合测试条件的第一个数组元素
索引
,如果没有符合条件的则返回 -1。
const list = [
{ name: '头部导航', id: 1 },
{ name: '轮播', id: 2 },
{ name: '页脚', id: 3 },
];
const result = list.find(item => item.id === 3);
// result: { name: '页脚', id: 3 }
const index = list.findIndex(item => item.id === 3);
// index: 2
小结
- 二者都是用来查找数组元素。
- find 方法返回数组中满足 callback 函数的第一个元素的值。如果不存在返回 undefined。
- findIndex 它返回数组中找到的元素的索引,而不是其值,如果不存在返回 -1。
reduce、reduceRight
reduce 方法接收两个参数,第一个参数是回调函数(callback)【必须】 ,第二个参数是初始值(initialValue)【可选】。
reduceRight 方法除了与 reduce 执行方向相反外(从右往左),其他完全与其一致。
array.reduce(function(total, current, currentIndex, sourceArray), initialValue)
回调函数接收四个参数:
- total:MDN 上解释为累计器,可以理解为它应该是截至当前元素,之前所有的数组元素被回调函数处理累计的结果。
- current:当前被执行的数组元素。
- currentIndex: 当前被执行的数组元素索引。
- sourceArray:原数组,也就是调用 reduce 方法的数组。
initialValue 可选。传递给函数的初始值
如果不传入初始值,reduce 方法会从索引 1 开始执行回调函数,如果传入初始值,将从索引 0 开始、并从初始值的基础上累计执行回调。
返回值: 返回计算结果
注意: reduce() 对于空数组
是不会执行回调函数的。
const list = [
{ name: 'left', width: 20 },
{ name: 'center', width: 70 },
{ name: 'right', width: 10 },
];
const total = list.reduce((currentTotal, item) => {
return currentTotal + item.width;
}, 0);
// total: 100