常见的遍历方法以及如何终止循环引发

385 阅读3分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

如何终止循环

终止循环的方法基本就是如下三种:

  1. break - 中止当前循环,switch语句或label 语句,并把程序控制流转到紧接着被中止语句后面的语句;
  2. continue - 终止当前循环或标记循环的当前迭代中的语句执行,并在下一次迭代时继续执行循环;
  3. return - 终止函数的执行,并返回一个指定的值给函数调用者;

以上的描述都是在 MDN 中摘抄来的,为了方便理解,可以看下面的小例子:

let arr = ['a', 'b', 'c', 'd']
for (let i = 0; i < arr.length; i++) {
  console.log('for:', arr[i])
  if (i === 2) {
    return
  }
}
// 输出 a b

for (let i = 0; i < arr.length; i++) {
  console.log('for:', arr[i])
  if (i === 2) {
    break
  }
}
// 输出 a b

for (let i = 0; i < arr.length; i++) {
  console.log('for:', arr[i])
  if (i === 2) {
    continue
  }
}
// 输出 a b d

通过上面的例子会发现在 for 循环中, break 和 return 的效果是类似的,但是使用 return 在开发中会直接停止当前函数继续向下执行,所以在开发中要明确自己需要实现的效果,不能盲目的使用。

常见的遍历方法

let arr = ['a', 'b', 'c']
let numArr = [1, 2, 3, 4, 5]
let user = {
  name: 'test',
  age: 18,
}
for (let i = 0; i < arr.length; i++) {
  console.log('for', arr[i])
}

// for in 遍历对象 i=key
for (let i in arr) {
  console.log('for in obj:', i)
}
// for in 遍历数组 i=index( 下标 )
for (let i in user) {
  console.log('for in arr:', i)
}

// for of 遍历数组 i = 数组中的值
// for of 不能遍历对象
for (let i of arr) {
  console.log('for of arr:', i)
}

// forEach 只能用于数组
// forEach 接受一个回调函数,第一个是此次循环的元素,第二个是此次循环的下标,第三个是当前正在操作的数组
// 除了抛出异常,没有其他办法终止 foreach 循环
arr.forEach((item, index, arr) => {
  console.log('arr foreach', item, index, arr)
  // return 会停止继续执行,但是循环不会停止
  // 因为当前的执行环境只是一个回调函数,所以 return 停止了当前函数的执行,但是循环并没有停止
  if (index === 1) {
    return false
  }
  console.log('test', index)
})

// map 只能用于数组
// 接受一个回调函数,第一个是此次循环的元素,第二个是此次循环的下标,第三个是当前正在操作的数组
// 除了抛出异常,没有其他办法终止循环
// 不会改变原数组,但是会返回根据 return 的值生成一个新的数组
let newArr = arr.map((item, index, arr) => {
  console.log(item, index, arr)
  return 'item:' + item
})
console.log(arr); // ['a', 'b', 'c', 'd']
console.log(newArr); // ['item:a', 'item:b', 'item:c', 'item:d']

// filter 只能用于数组
// 接受一个回调函数,第一个是此次循环的元素,第二个是此次循环的下标,第三个是当前正在操作的数组
// 除了抛出异常,没有其他办法终止循环
// 不会改变原数组,但是会返回将根据满足条件的值生成一个新的数组
let filterNewArr = arr.filter((item, index, arr) => {
  console.log(item, index, arr)
  return item !== 'a'
})
console.log(arr) // ['a', 'b', 'c', 'd']
console.log(filterNewArr) // ['b', 'c', 'd']

// 测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值
// 若收到一个空数组,此方法在一切情况下都会返回 true
// 如果有一个值不符合,则立即返回 false
let everyNum = numArr.every((item, index, arr) => {
  console.log(item, index, arr)
  return item > 3
})
console.log(everyNum)

// 测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回一个布尔值
// 若收到一个空数组,此方法在一切情况下都会返回 false
// 如果有一个满足条件,则立即返回 true
let someNum = numArr.some((item, index, arr) => {
  console.log(item, index, arr)
  return item > 3
})
console.log(someNum)

// 返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
let findNum = numArr.find((item, index, arr) => {
  console.log(item, index, arr)
  return item > 3
})
console.log(findNum)

// 返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。
let findIndexNum = numArr.findIndex((item, index, arr) => {
  console.log(item, index, arr)
  return item > 3
})
console.log(findIndexNum)

MDN:every 遍历的元素范围在第一次调用 callback 之前就已确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到。如果数组中存在的元素被更改,则他们传入 callback 的值是 every 访问到他们那一刻的值。那些被删除的元素或从来未被赋值的元素将不会被访问到。

every / some / find / findIndex 都只能用于数组且不会改变原数组;并且这四个方法在开始遍历时范围就已经确定了,后续的任何修改都不会影响到当前遍历的结果

记录这篇笔记是为了以后不要每次有数据处理的需求时抬手就是一个 for 循环,可以根据情况选择不同的函数进行处理。