前端面试题:你能终止 forEach循环吗?

194 阅读2分钟

不能被终止的forEach?

面试官:你有什么办法终止 forEach 循环吗?

我:emm,没办法。

面试官:面试到此结束!

我:???

为什么我认为无法终止 forEach 循环?

const array = [ -3, -2, -1, 0, 1, 2, 3 ]

array.forEach((it) => {
  if (it >= 0) {
    console.log(it)
    return // or break
  }
})

image-20240310210523718

这段代码没问题,我们甚至还可以模拟实现一下forEach

Array.prototype.forEach2 = function (callback, thisCtx) {
  if (typeof callback !== 'function') {
    throw `${callback} is not a function`
  }

  const length = this.length

  let i = 0
  while (i < length) {
    if (this.hasOwnProperty(i)) {
      // Note here:Each callback function will be executed once
      callback.call(thisCtx, this[ i ], i, this)
    }
    i++
  }
}

是的,当我们使用“forEach”迭代数组时,回调将为数组的每个元素执行一次,并且我们无法提前终止它。

三种方法终止 forEach

前面说的都没错,但是其实我们有三种特殊方法来终止 forEach 循环

# 抛出错误

当我们找到第一个大于或等于0的数字后,这段代码将无法继续。所以控制台只会打印出0。

const array = [ -3, -2, -1, 0, 1, 2, 3 ]

try {
  array.forEach((it) => {
    if (it >= 0) {
      console.log(it)
      throw Error(`We've found the target element.`)
    }
  })
} catch (err) {
  
}

image-20240310211613497

# 设置数组长度为0

我们还可以通过将数组的长度设置为0来中断forEach。如果数组的长度为0,forEach将不会执行任何回调。

const array = [ -3, -2, -1, 0, 1, 2, 3 ]

array.forEach((it) => {
  if (it >= 0) {
    console.log(it)
    array.length = 0
  }
})

image-20240310211740962

# 使用splice删除数组的元素

思路和方法2一样,如果能删除目标元素后面的所有值,那么forEach就会自动停止。

const array = [ -3, -2, -1, 0, 1, 2, 3 ]

array.forEach((it, i) => {
  if (it >= 0) {
    console.log(it)
    // Notice the sinful line of code
    array.splice(i + 1, array.length - i)
  }
})

image-20240310211842578

请用 for OR some

虽然这三种方法能够终止 forEach 循环,但是并不推荐在实际工作中使用这些方式,因为实在太过恶臭。最好还是使用 for 或者 some 来实现。

for

const array = [ -3, -2, -1, 0, 1, 2, 3 ]

for (let i = 0, len = array.length; i < len; i++) {
  if (array[ i ] >= 0) {
    console.log(array[ i ])
    break
  }
}

image-20240310212104669

some

const array = [ -3, -2, -1, 0, 1, 2, 3 ]

array.some((it, i) => {
  if (it >= 0) {
    console.log(it)
    return true
  }
})

image-20240310212129562