你的位置:【欧冠体育官方首页】 > 礼仪庆典 > 二十一 个 JavaScript 循环遍历编制,你都晓得吗?
礼仪庆典
二十一 个 JavaScript 循环遍历编制,你都晓得吗?
发布日期:2022-08-07 08:24    点击次数:124

 

来日诰日我们来看点根抵知识,看看JavaScript中的那些循环遍历编制:

1、数组遍历编制 1. forEach()

forEach 编制用于调用数组的每个元素,并将元素通报给回调函数。数组中的每个值都市调用回调函数。其语法以下: 

array.forEach(function(currentValue, index, arr), thisValue) 

该编制的第一个参数为回调函数,是必传的,它有三个参数:

 currentValue:必须。今后元素  index:可选。今后元素的索引值。  arr:可选。今后元素所属的数组工具 
let arr = [1,2,3,4,5]  arr.forEach((item, index, arr) => {    console.log(index+":"+item)  }) 

该编制还可以或许有第二个参数,用来绑定回调函数外部this变量(条件是回调函数不克不迭是箭头函数,因为箭头函数没有this): 

let arr = [1,2,3,4,5]  let arr1 = [9,8,7,6,5]  arr.forEach(function(item, index, arr){   console.log(this[index])  //  9 8 7 6 5  }, arr1) 

留心:

 forEach 编制不会改变原数组,也没有前去值;  forEach没法运用 break,continue 跳出循环,运用 return 时,结果和在 for 循环中运用 continue 分歧;  forEach 编制没法遍历工具,仅实用于数组的遍历。 2. map()

map() 编制会前去一个新数组,数组中的元素为原始数组元素调用函数处理惩罚后的值。该编制根据原始数组元素按次顺次处理惩罚元素。其语法以下: 

array.map(function(currentValue,index,arr), thisValue) 

该编制的第一个参数为回调函数,是必传的,它有三个参数:

 currentValue:必须。今后元素的值;  index:可选。今后元素的索引值;  arr:可选。今后元素属于的数组工具。 
let arr = [1, 2, 3];   arr.map(item => {      return item + 1;  })  // 输出终局: [2, 3, 4] 

该编制的第二个参数用来绑定参数函数外部的this变量,是可选的: 

let arr = ['a', 'b', 'c'];   [1, 2].map(function (e) {      return this[e];  }, arr)  // 输出终局: ['b', 'c'] 

该编制还可以或许举行链式调用: 

let arr = [1, 2, 3];   arr.map(item => item + 1).map(item => item + 1)  // 输出终局: [3, 4, 5] 

留心:

 map 编制不会对空数组举行检测;  map 编制遍历数组时会前去一个新数组,不会改变原始数组;  map 编制有前去值,可以或许return进去,map的回调函数中支持return前去值;  map 编制没法遍历工具,仅实用于数组的遍历。 3. for of

for...of 语句创立一个循环来离去迭代可迭代的工具。在 ES6 中引入的 for...of 循环,以改换 for...in 和 forEach() ,并支持新的迭代和谈。其语法以下: 

for (variable of iterable) {      statement  } 

该编制有两个参数:

 variable:每个迭代的属性值被分派给该变量。  iterable:一个具有可罗列属性并且可以或许迭代的工具。

该编制可以或许取得数组的每一项: 

let arr = [      {id:1, value:'hello'},      {id:2, value:'world'},      {id:3, value:'JavaScript'}  ]  for (let item of arr) {   console.log(item);   }  // 输出终局:{id:1, value:'hello'}  {id:2, value:'world'} {id:3, value:'JavaScript'} 

留心:

 for of 编制只会遍历今后工具的属性,不会遍历其原型链上的属性;  for of 编制实用遍历 数组/ 类数组/字符串/map/set 等拥有迭代器工具的鸠合;  for of 编制不支持遍历通俗工具,因为其没有迭代器工具。假定想要遍历一个工具的属性,可以或许用 for in 编制;  可运用break、continue、return来中缀循环遍历; 4. filter()

filter()编制用于过滤数组,餍足条件的元素会被前去。它的参数是一个回调函数,全体数组元素顺次执行该函数,前去终局为true的元素会被前去,假定没有吻合条件的元素,则前去空数组。其语法以下: 

array.filter(function(currentValue,index,arr), thisValue) 

该编制的第一个参数为回调函数,是必传的,它有三个参数:

 currentValue:必须。今后元素的值;  index:可选。今后元素的索引值;  arr:可选。今后元素属于的数组工具。 
const arr = [1, 2, 3, 4, 5]  arr.filter(item => item > 2)   // 输出终局:[3, 4, 5] 

同样,它也有第二个参数,用来绑定参数函数外部的this变量。

可运用filter()编制来移除数组中的undefined、null、NAN等值: 

let arr = [1, undefined, 2, null, 3, false, '', 4, 0]  arr.filter(Boolean)  // 输出终局:[1, 2, 3, 4] 

留心:

 filter 编制会前去一个新的数组,不会改变原数组;  filter 编制不会对空数组举行检测;  filter 编制仅实用于检测数组。 5. some()、every()

some() 编制会对数组中的每一项举行遍历,只需有一个元素吻合条件,就前去true,且残剩的元素不会再举行检测,否则就前去false。

every() 编制会对数组中的每一项举行遍历,只要全体元素都吻合条件时,才前去true,假定数组中检测到有一个元素不餍足,则全副剖明式前去 false ,且残剩的元素不会再举行检测。其语法以下:

两者的语法以下: 

array.some(function(currentValue,index,arr),thisValue)  array.every(function(currentValue,index,arr), thisValue) 

两个编制的第一个参数为回调函数,是必传的,它有三个参数:

 currentValue:必须。今后元素的值;  index:可选。今后元素的索引值;  arr:可选。今后元素属于的数组工具。 
let arr = [1, 2, 3, 4, 5]  arr.some(item => item > 4)   // 输出终局:true  let arr = [1, 2, 3, 4, 5]  arr.every(item => item > 0)   // 输出终局:true 

留心:

 两个编制都不会改变原数组,会前去一个布尔值;  两个编制都不会对空数组举行检测;  两个编制都仅实用于检测数组。 6. reduce()、reduceRight()

reduce() 编制领受一个函数作为累加器,数组中的每个值(从左到右)起头缩减,终究计算为一个值。reduce() 可以或许作为一个高阶函数,用于函数的 compose。其语法以下: 

array.reduce(function(total, currentValue, currentIndex, arr), initialValue) 

reduce 编制会为数组中的每个元素顺次执行回调函数,不蕴含数组中被删除或从未被赋值的元素,回调函数担任四个参数:

 total:上一次调用回调前去的值,或许是供应的初始值(initialValue);  currentValue:今后被处理惩罚的元素;  currentIndex:今后元素的索引;  arr:今后元素所属的数组工具。

该编制的第二个参数是 initialValue,默示通报给函数的初始值 (作为第一次调用 callback 的第一个参数): 

let arr = [1, 2, 3, 4]  let sum = arr.reduce((prev, cur, index, arr) => {      console.log(prev, cur, index);      return prev + cur;  })  console.log(arr, sum); 

输出终局: 

1 2 1  3 3 2  6 4 3  [1, 2, 3, 4] 10 

再来加一个初始值试试: 

let arr = [1, 2, 3, 4]  let sum = arr.reduce((prev, cur,礼仪庆典 index, arr) => {      console.log(prev, cur, index);      return prev + cur;  }, 5)  console.log(arr, sum); 

输出终局: 

5 1 0  6 2 1  8 3 2  11 4 3  [1, 2, 3, 4] 15 

由此可以或许得出结论:假定没有供应初始值initialValue,reduce 会从索引1之处起头执行 callback 编制,跳过第一个索引。假定供应了初始值initialValue,从索引0起头执行

reduceRight() 编制和的reduce()用法险些分歧,只是该编制是对数组举行倒序遍历的,而reduce()编制是正序遍历的。 

let arr = [1, 2, 3, 4]  let sum = arr.reduceRight((prev, cur, index, arr) => {      console.log(prev, cur, index);      return prev + cur;  }, 5)  console.log(arr, sum); 

输出终局: 

5 4 3  9 3 2  12 2 1  14 1 0  [1, 2, 3, 4] 15 

留心:

 两个编制都不会改变原数组;  两个编制假定增加初始值,就会改变原数组,会将这个初始值放在数组的最后一位;  两个编制关于空数组是不会执行回调函数的。 7. find()、findIndex()

find() 编制前去经由过程函数内鉴定的数组的第一个元素的值。当数组中的元素在测试条件时前去 true 时, find() 前去吻合条件的元素,今后的值不会再调用执行函数。假定没有吻合条件的元素前去 undefined。

findIndex() 编制前去传入一个测试函数吻合条件的数组第一个元素职位地方(索引)。当数组中的元素在函数条件时前去 true 时, findIndex() 前去吻合条件的元素的索引职位地方,今后的值不会再调用执行函数。假定没有吻合条件的元素前去 -1。

两个编制的语法以下: 

array.find(function(currentValue, index, arr),thisValue)  array.findIndex(function(currentValue, index, arr), thisValue) 

两个编制的第一个参数为回调函数,是必传的,它有三个参数:

 currentValue:必须。今后元素;  index:可选。今后元素的索引;  arr:可选。今后元素所属的数组工具。 
let arr = [1, 2, 3, 4, 5]  arr.find(item => item > 2)   // 输出终局:3  let arr = [1, 2, 3, 4, 5]  arr.findIndex(item => item > 2)   // 输出终局:2 

find()和findIndex()两个编制险些同样,只是前去终局差别:

 find():前去的是第一个吻合条件的值;  findIndex:前去的是第一个前去条件的值的索引值。

留心:

 两个编制关于空数组,函数是不会执行的;  两个编制否不会改变原数组。 8. keys()、values()、entries()

三个编制都前去一个数组的迭代工具,工具的内容不太沟通:

 keys() 前去数组的索引值;  values() 前去数组的元素;  entries() 前去数组的键值对。

三个编制的语法以下: 

array.keys()  array.values()  array.entries() 

这三个编制都没有参数: 

let arr = ["Banana", "Orange", "Apple", "Mango"];  const iterator1 = arr.keys();  const iterator2 = arr.values()   const iterator3 = arr.entries()   for (let item of iterator1) {    console.log(item);  }  // 输出终局: 0 1 2 3  for (let item of iterator2) {   console.log(item);  }  // 输出终局:Banana Orange Apple Mango  for (let item of iterator3) {    console.log(item);  }  // 输出终局:[0, 'Banana'] [1, 'Orange'] [2, 'Apple'] [3, 'Mango'] 

总结:

编制 是否改变原数组 特征 forEach() 否 没有前去值 map() 否 有前去值,可链式调用 for of 否 for...of遍历具有Iterator迭代器的工具的属性,前去的是数组的元素、工具的属性值,不克不迭遍历通俗的obj工具,将异步循环变成同步循环 filter() 否 过滤数组,前去包孕吻合条件的元素的数组,可链式调用 every()、some() 否 some()只需有一个是true,便前去true;而every()只需有一个是false,便前去false. find()、findIndex() 否 find()前去的是第一个吻合条件的值;findIndex()前去的是第一个前去条件的值的索引值 reduce()、reduceRight() 否 reduce()对数组正序操作;reduceRight()对数组逆序操作 keys()、values()、entries() 否 keys() 前去数组的索引值;values() 前去数组元素;entries() 前去数组的键值对。 2、工具遍历编制 1. for in

for…in 次要用于循环工具属性。循环中的代码每执行一次,就会对工具的属性举行一次操作。其语法以下: 

for (var in object) {   执行的代码块  } 

个中两个参数:

 var:必须。指定的变量可以是数组元素,也可以是工具的属性。  object:必须。指定迭代的的工具。 
var obj = {a: 1, b: 2, c: 3};    for (var i in obj) {      console.log('键名:', i);       console.log('键值:', obj[i]);   } 

输出终局: 

键名:a  键值: 1  键名:b  键值: 2  键名:c  键值: 3 

留心:

for in 编制不只会遍历今后的工具全体的可罗列属性,还会遍历其原型链上的属性。

2. Object.keys()、Object.values()、Object.entries()

这三个编制都用来遍历工具,它会前去一个由给定工具的本身可罗列属性(不含继承的和Symbol属性)形成的数组,数组元素的陈设按次和畸形循环遍历该工具时前去的按次分歧,这个三个元素前去的值划分以下:

 Object.keys():前去包孕工具键名的数组;  Object.values():前去包孕工具键值的数组;  Object.entries():前去包孕工具键名和键值的数组。 
let obj = {     id: 1,     name: 'hello',     age: 18   };  console.log(Object.keys(obj));   // 输出终局: ['id', 'name', 'age']  console.log(Object.values(obj)); // 输出终局: [1, 'hello', 18]  console.log(Object.entries(obj));   // 输出终局: [['id', 1], ['name', 'hello'], ['age', 18] 

留心

 Object.keys()编制前去的数组中的值都是字符串,也就是说不是字符串的key值会转化为字符串。  终局数组中的属性值都是工具本身可罗列的属性,不蕴含继承来的属性。 3. Object.getOwnPropertyNames()

Object.getOwnPropertyNames()编制与Object.keys()近似,也是担任一个工具作为参数,前去一个数组,包孕了该工具本身的全体下性名。但它能前去弗成罗列的属性。 

let a = ['Hello', 'World'];   Object.keys(a) // ["0", "1"]  Object.getOwnPropertyNames(a) // ["0", "1", "length"] 

这两个编制均可以或许用来计算工具中属性的个数: 

var obj = { 0: "a", 1: "b", 2: "c"};  Object.getOwnPropertyNames(obj) // ["0", "1", "2"]  Object.keys(obj).length // 3  Object.getOwnPropertyNames(obj).length // 3 
4. Object.getOwnPropertySymbols()

Object.getOwnPropertySymbols() 编制前去工具本身的 Symbol 属性形成的数组,不蕴含字符串属性: 

let obj = {a: 1}  // 给工具增加一个弗成罗列的 Symbol 属性  Object.defineProperties(obj, {   [Symbol('baz')]: {    value: 'Symbol baz',    enumerable: false   }  })  // 给工具增加一个可罗列的 Symbol 属性  obj[Symbol('foo')] = 'Symbol foo'  Object.getOwnPropertySymbols(obj).forEach((key) => {   console.log(obj[key])   })  // 输出终局:Symbol baz Symbol foo 
5. Reflect.ownKeys()

Reflect.ownKeys() 前去一个数组,包孕工具本身的全体下性。它和Object.keys()近似,Object.keys()前去属性key,但不蕴含弗成罗列的属性,而Reflect.ownKeys()会前去全体下性key: 

var obj = {   a: 1,   b: 2  }  Object.defineProperty(obj, 'method', {   value: function () {       alert("Non enumerable property")   },   enumerable: false  })   console.log(Object.keys(obj))  // ["a", "b"]  console.log(Reflect.ownKeys(obj))  // ["a", "b", "method"] 

留心:

 Object.keys() :相当于前去工具属性数组;  Reflect.ownKeys() :相当于 Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)。

总结:

工详细例 遍历根抵属性 遍历原型链 遍历弗成罗列属性 遍历Symbol for in 是 是 否 否 Object.keys() 是 否 否 否 Object.getOwnPropertyNames() 是 否 是 否 Object.getOwnPropertySymbols() 否 否 是 是 Reflect.ownKeys() 是 否 是 是 3、别的遍历编制 1. for

for循环是该当是至多见的循环编制了,它由三个剖明式形成,划分是声名循环变量、鉴定循环条件、更新循环变量。这三个剖明式用分号分开。可运用暂且变量将数组的长度缓存起来,防止重复取得数组长度,当数组较大时优化结果会相比分明。 

const arr = [1,2,3,4,5]  for(let i = 0, len = arr.length; i < len; i++ ){    console.log(arr[i])  } 

在执行的岁月,会先鉴定执行条件,再执行。for循环可以或许用来遍历数组,字符串,类数组,DOM节点等。可以或许改变原数组。

2. while

while循环中的终止条件可以是各类范例,然则终究都市转为布尔值,转换划定端方以下。

 Boolean:true为真,false为假;  String:空字符串为假,全体非空字符串为真;  Number:0为假,非0数字为真;  null/Undefined/NaN:全为假;  Object:全为真。 
let num = 1;        while (num < 10){      console.log(num);     num ++;  } 

while和for同样,都是先鉴定,再执行。只需指定条件为 true,循环就能一贯执行代码。

3. do / while

该编制会先执行再鉴定,纵然初始条件弗成立,do/while循环也起码会执行一次。 

let num = 10;           do   {      console.log(num);      num--;    }  while(num >= 0);            console.log(num); //-1 

不倡导运用do / while来遍历数组。

4. for await of

for await...of编制被称为异步迭代器,该编制是次要用来遍历异步工具。它是ES2018中引入的编制。

for await...of 语句会在异步或许同步可迭代工具上创立一个迭代循环,蕴含 String,Array,类数组,Map, Set和自定义的异步或许同步可迭代工具。这个语句只能在 async function内运用: 

function Gen (time) {    return new Promise((resolve,reject) => {      setTimeout(function () {         resolve(time)      },time)    })  }  async function test () {     let arr = [Gen(2000),Gen(100),Gen(3000)]     for await (let item of arr) {        console.log(Date.now(),item)     }  }  test() 

输出终局: