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)
- 首先接收一個回調
callbackFn
,回調用三個參數(element, index, array)element
:數組中正在處理的當前元素;index
:數組中正在處理的當前元素的索引;array
:調用了 forEach() 的數組本身。
- 函數沒有返回值,默認爲
undefined
。
2.3 自定義myForEach
-
這裏我把自己定義的方法寫在數組的原型上,好處就是可複用性, 根據上邊得到的信息,我們需要接收一個
回調函數(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循環中是一個函數執行,我們最開始的寫法就是說我們的return
和break
是寫在了我們的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或者是其他循環函數。