1. 首页
  2. 前端

浅谈JavaScript中热闹的循环及使用方法详细介绍

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() 返回 falsecallback 只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。

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

发表评论

电子邮件地址不会被公开。 必填项已用*标注

联系我们

在线咨询:点击这里给我发消息

邮件:499661635@qq.com.com

工作时间:周一至周五,9:30-18:30

QR code