在JavaScript中,提到循环,大概都不陌生。在js中,循环的方法有很多很多 ,如:for,forEach,for ……in,map,for……of ,filter,every,some,in等等,对于这些循环都能熟练的使用吗,今天就针对于循环进行一一讲解。
1.for循环
说到for循环,大家都再熟悉不过了,这里就简要的举个例子就可以了。
var array = ['banner','apple','pear','orange']; for (var i = 0; i < array.length;i++) { console.log(array[i]); } //banner apple pear orange
2.for ……in循环
for...in
语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。
语法:for (variable in object) {…}
变量 | 对象 |
---|---|
variable | 在每次迭代时,将不同的属性名分配给变量 |
object | 被迭代枚举其属性的对象 |
for...in
循环只遍历可枚举属性,在查找对象属性时遍历原型链上的所有属性,如:
var obj = {a:1, b:2, c:3}; for (var i in obj) { console.log("obj." + i + " = " + obj[i]); } // "obj.a = 1" // "obj.b = 2" // "obj.c = 3"
但是for…in与for室友区别的,需要注意点如下:
(1).遍历普通数组,建议使用for,不要贪图方便,因为for in存在浏览器的兼容问题,不能保证它们对数组的遍历顺序。
(2).遍历对象建议使用for in。
使用for in 也可以遍历数组,但是会存在以下问题:
1.index索引为字符串型数字,不能直接进行几何运算。
2.遍历顺序有可能不是按照实际数组的内部顺序。
3.使用for in会遍历数组所有的可枚举属性,包括原型。
3.for ……of循环
在介绍for…of之前,先来举个例子和for… in对比下。
let arr = ['a', 'b', 'c']; for(let i in arr) { console.log(i); //0 1 2 }
let arr = ['a', 'b', 'c']; for(let i of arr) { console.log(i); //a b c }
通过例子发现:for… in中的变量i是元素的下标;for…of中的变量i遍历的结果是元素的值。
那么要实现和for…in类似的,获取下标,如何实现呢?其实for…of中的数组arr有个keys()方法,直接调用即可,对上面的for…of例子稍微改下如下:
let arr = ['a', 'b', 'c']; for(let i of arr.keys()) { console.log(i); //0 1 2 }
如果要获取各项实体,那么如何实现呢,其实for…of的数组对象还有个entries(),实现例子如下:
let arr = ['a', 'b', 'c']; for(let i of arr.entries()) { console.log(i); } //[0,"a"] [1,"b"] [2,"c"]
那 for-of 到底可以干什么呢?
- 跟 forEach 相比,可以正确响应 break, continue, return。
- for-of 循环不仅支持数组,还支持大多数类数组对象,例如 DOM nodelist 对象。
- for-of 循环也支持字符串遍历,它将字符串视为一系列 Unicode 字符来进行遍历。
- for-of 也支持 Map 和 Set (两者均为 ES6 中新增的类型)对象遍历。
总结一下,for-of 循环有以下几个特征:
- 这是最简洁、最直接的遍历数组元素的语法。
- 这个方法避开了 for-in 循环的所有缺陷。
- 与 forEach 不同的是,它可以正确响应 break、continue 和 return 语句。
- 其不仅可以遍历数组,还可以遍历类数组对象和其他可迭代对象。
但需要注意的是,for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用 for-in 循环(这也是它的本职工作)。
4.forEach循环
forEach循环是在ES5 中新增的方法,可以代替普通的for循环。
首先说下JavaScript的forEach的标准格式。
array1.forEach(callbackfn[, thisArg])
参数 | 定义 |
---|---|
array1 | 必需。 一个数组对象。 |
callbackfn | 必需。 一个接受最多三个参数的函数。 对于数组中的每个元素,forEach 都会调用 callbackfn 函数一次。 |
thisArg | 可选。 可在 callbackfn 函数中为其引用 this 关键字的对象。 如果省略 thisArg,则 undefined 将用作 this 值。 |
如果 callbackfn 参数不是函数对象,则将引发 TypeError 异常。
对于数组中的每个元素,forEach 方法都会调用 callbackfn 函数一次(采用升序索引顺序),不为数组中缺少的元素调用该回调函数。
除了数组对象之外,forEach 方法可由具有 length 属性且具有已按数字编制索引的属性名的任何对象使用。
回调函数语法
回调函数的语法如下所示:
function callbackfn(value, index, array)
可使用最多三个参数来声明回调函数。
回调函数的参数如下所示:
回调参数 | 定义 |
---|---|
value | 数组元素的值。 |
index | 数组元素的数字索引。 |
array | 包含该元素的数组对象。 |
注:forEach 方法不直接修改原始数组,但回调函数可能会修改它,forEach 没有返回值。
例子:
var array = ['banner','apple','pear','orange'];
array.forEach(function(val,index,item){
console.log(val)
})
5.map循环
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
标准的语法格式如下:
arr.map(callback(value, index, array){ }, this)
map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素
, 元素索引
, 原数组本身
.
参数 | 定义 |
---|---|
value | 数组元素的值(当前正在遍历的元素 ) |
index | 数组元素的数字索引(元素索引 ) |
array | 包含该元素的数组对象(原数组本身 ) |
var array = [
{ title:'apple', kil:'45' },
{ title:'banner', kil:'60' },
{ title:'pear', kil:'38' }
];
var newArray=array.map(function(val,index,item){
console.log(val,index,item)
return val
})
console.log(newArray)
总结说明:
(1).正常情况下,需要配合return,返回一个新的数组。若是没有return,相当于forEach。
平时只要用map,一定要有return。
(2).通常情况下,map 方法中的 callback 函数只需要接受一个参数(很多时候,自定义的函数形参只有一个),就是正在被遍历的数组元素本身。
但这并不意味着 map 只给 callback 传了一个参数(会传递3个参数)。
(3).map()方法不会影响原数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了
6.filter循环
filter()方法创建一个新的匹配过滤条件的数组,即filter()方法将数组中的某些元素过滤掉,返回剩下的元素。
和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
语法:
var new_array = arr.filter(callback(value[, index[, array]])[, thisArg])
callback
用来测试数组的每个元素的函数。调用时使用参数 (element, index, array)。
返回true表示保留该元素(通过测试),false则不保留。它接受三个参数:
参数 | 定义 |
---|---|
value | 当前在数组中处理的元素(元素的值) |
index | 可选。正在处理元素在数组中的索引(元素的索引) |
array | 可选。调用了filter 的数组(被遍历的数组) |
thisArg | 可选。执行 callback 时的用于 this 的值 |
返回值:一个新的通过测试的元素的集合的数组,如果没有通过测试则返回空数组。
var filtered = [12, 5, 8, 130, 44].filter((value,index,arr)=>{ return value >= 10 }); console.log(filtered) // filtered is [12, 130, 44]
(1).果为 filter
提供一个 thisArg
参数,则它会被作为 callback
被调用时的 this
值。否则,callback
的 this
值在非严格模式下将是全局对象,严格模式下为 undefined
。
(2).filter
不会改变原数组,它返回过滤后的新数组。
7.some循环
some() 方法类似查找,用于检测数组中某一项元素是否满足指定条件,如果满足,则返回true,否则返回false。
some()
为数组中的每一个元素执行一次 callback
函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,some()
将会立即返回 true
。否则,some()
返回 false
。callback
只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。
some() 方法会依次执行数组的每个元素:
- 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
- 如果没有满足条件的元素,则返回false。
注意: some() 不会对空数组进行检测,对于放在空数组上的任何条件,此方法返回false
。
注意: some() 不会改变原始数组。
语法:
arr.some(callback(value[, index[, array]])[, thisArg])
callback
用来测试每个元素的函数,接受三个参数:
参数 | 定义 |
---|---|
value | 当前在数组中处理的元素(元素的值) |
index | 可选。正在处理元素在数组中的索引(元素的索引) |
array | 可选。some() 被调用的数组(被遍历的数组) |
thisArg | 可选。执行 callback 时的用于 this 的值 |
返回值:如果数组中有元素满足条件返回 true,否则返回 false。
例子:检测在数组中是否有元素大于 10。
function isBiggerThan(element, index, array) { return element > 10; } [2, 5, 8, 1, 4].some(isBiggerThan); // false [12, 5, 8, 1, 4].some(isBiggerThan); // true
8.every循环
every()方法测试数组的所有元素是否都通过了指定函数的测试。即:数组里面所有的元素都要满足条件,才返回true,否则返回false。
callback
只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用。
语法:
arr.every(callback[, thisArg])
callback
用来测试每个元素的函数。thisArg
执行callback
时使用的this
值。
注意: every() 不会对空数组进行检测。
注意: every() 不会改变原始数组。
callback
同样接收三个参数:
参数 | 定义 |
---|---|
value | 必须。当前元素的值 |
index | 可选。正在处理元素在数组中的索引(元素的索引) |
array | 可选。当前元素属于的数组对象 |
返回值:如果数组中所有元素都满足条件返回 true,否则返回 false。
9.reduce循环
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce() 是一个高阶函数,用于函数的 compose。
官方的解释大家可能听得比较含糊,别担心,看了下面的例子,你将会清楚它。
语法:
arr.reduce(callback[, initialValue])
callback回调函数的参数如下:
参数 | 定义 |
---|---|
acc | 必须。累计器(它是上一次调用回调时返回的累积值) |
cur | 可选。当前值 |
Index | 可选。当前索引 |
Array | 可选。当前元素属于的数组对象 |
initialValue
作为第一次调用 callback函数时
的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错
返回值:返回累计计算的结果
注意:
(1).reduce() 对于空数组是不会执行回调函数的。
(2).如果没有提供initialValue
,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue
,从索引0开始。
例子:例1:求数组中数字幂次方,即阶乘,即(2^3)^4
let arr=[2,2,3] let res = arr.reduce((prev,cur,index,arr)=>{ return prev**cur }) console.log(res) //64
例2:求和
//用reduce,即1+2+3+4+5+6+7+8+9+10的和 let arr=[1,2,3,4,5,6,7,8,9,10] let res = arr.reduce((prev,cur,index,arr)=>{ return prev+cur }) console.log(res) //55
10.reduceRight循环
reduceRight()
方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值,其用法和reduce很相似,只是reduce是从左到右,reduceRight是从右到左,具体用法请参见reduce。
举例:
例1:求数组中数字幂次方,即阶乘,即(3^2)^2
let arr=[2,2,3] let res = arr.reduceRight((prev,cur,index,arr)=>{ return prev**cur }) console.log(res) //81
例2:求和
//用reduceRight,即10+9+8+7+6+5+4+3+2+1的和 let arr=[1,2,3,4,5,6,7,8,9,10] let res = arr.reduceRight((prev,cur,index,arr)=>{ return prev+cur }) console.log(res) //55
实际项目中,至于选择哪个方法,需根据具体需求具体选择。最后一个方法reduceRiht的实际应用场景,目前还没遇到过,至于它到底有什么真实的使用价值,还需要在具体的需求中体会。
原创文章,作者:Ferrycoln,如若转载,请注明出处:https://ms200.cn/archives/776