JS中爲什麼forEach方法不能終止

forEach是我們在日常工作中經常使用到的方法,但是你有什麼嘗試使用forEach進行停止終止等操作呢?

一、走進forEach

對於forEach瞭解不多的,只知道它可以遍歷數組,如果有這麼一個操作: 一個數組[0, 1, 2, 3, 4, 5],打印出[0, 1, 2, 3],可能會這麼寫。

1.1 嘗試return

const arr = [0, 1, 2, 3, 4, 5];
const newArr = [];

arr.forEach(item => {
	newArr.push(item);
	if (item === 3) {
		return false;
	}
})

console.log(newArr); // ???

  

打印的結果不盡人意,還是 [0, 1, 2, 3, 4, 5]。爲什麼會這樣呢?

首先我們得出了一個結論,forEach不能通過return終止運行

1.2 嘗試break

我們在嘗試一下for循環中的break,看看效果會不會好一點。

const arr = [0, 1, 2, 3, 4, 5];
const newArr = [];

arr.forEach(item => {
	newArr.push(item);
	if (item === 3) {
		break; // SyntaxError: Illegal break statement
	}
})

console.log(newArr); // ???

  

結果報錯了:語法錯誤,非法的break語句。

二、剖析forEach

對於上邊的結果,我們就來看一看forEach實現原理到底是怎麼樣的,我猜想萬變不離其宗,說到底還是for循環

2.1 forEach使用

const arr = [0, 1, 2, 3, 4, 5];

arr.forEach((item, index, arr) => {
	console.log(item, index, arr);
})

  

 遍歷的三個值分別爲:值、下標、調用方法的數組對象

2.2 forEach分析

我們先來看一下forEach的特點,爲此我專門去MDN上看了一下,得到了以下信息:

forEach(callbackFn)

  

  1. 首先接收一個回調callbackFn,回調用三個參數(element, index, array)
    • element:數組中正在處理的當前元素;
    • index:數組中正在處理的當前元素的索引;
    • array:調用了 forEach() 的數組本身。
  2. 函數沒有返回值,默認爲undefined

2.3 自定義myForEach

  1. 這裏我把自己定義的方法寫在數組的原型上,好處就是可複用性, 根據上邊得到的信息,我們需要接收一個回調函數(fn),通過for循環改變fn的this指向,具體代碼如下: 下面我們來簡單分析一下

Array.prototype.myForEach = function (fn) {
	for (let i = 0; i < this.length; i ++) {
		fn.call(this, this[i], i, this);
	}
}

  2. 使用一下自己寫好的myForEach看一下打印的結果

const arr = [0, 1, 2, 3, 4, 5];

arr.myForEach((item, index, arr) => {
    console.log(item, index, arr);
})

 不能說完全相同只能說是一模一樣

2.4 深入解析forEach

通過2.3我們可以看到我們的for循環中是一個函數執行,我們最開始的寫法就是說我們的returnbreak是寫在了我們的fn中。於是我們就想到了下邊這種情況它可以終止嗎:

const arr = [0, 1, 2, 3, 4, 5];

for (let i = 0; i < arr.length; i ++) {
    fn(arr[i], i, arr);
}

function fn (item, index, array) {
    console.log(item, index, arr);
    if (item === 3) {
        return false;
    }
}

顯然這樣是不可以的,所以forEach不能停止

p.s 有一種不推薦的做法是可以終止的,就是在循環體裏拋出異常。

eg.

 輸出

 

三、改造myForEach

題外話:我這可能屬於是喫飽了沒事情做,哈哈

3.1 想法

試想一下,我們能不能通過改造一下我們自己定義的myForEach方法,來達到滿足我們的要求,相信聰明的你也能夠想到,讓for循環終止,我就簡單寫一下自己的想法把,我們讓fn有返回值,在for循環中通過flag變量接收。

3.2 代碼實現

Array.prototype.myForEach = function (fn) {
  for (let i = 0; i < this.length; i++) {
    const flag = fn.call(this, this[i], i, this);
    if (flag) {
      break
    }
  }
}

const arr = [0, 1, 2, 3, 4, 5];

arr.myForEach((item, index, array) => {
  console.log(item, index, array)
  if (item === 3) {
    return true
  }
})

 p.s jq的each就是return false中斷的,都是大同小異。

四、總結

  如果一定要跳出當前循環的操作,就不要用forEach。直接用for或者是其他循環函數。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章