forEach
是我們?cè)谌粘9ぷ髦薪?jīng)常使用到的方法,但是你有什么嘗試使用forEach
進(jìn)行停止
或終止
等操作呢?今天我就遇到了這個(gè)問(wèn)題,借此來(lái)剖析一下。
一、走進(jìn)forEach 之前對(duì)于forEach
了解的并不多,只知道它可以遍歷數(shù)組,如果有這么一個(gè)操作: 一個(gè)數(shù)組[0, 1, 2, 3, 4, 5]
,打印出[0, 1, 2, 3]
,對(duì)于聰明的我可能會(huì)這樣寫。
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); // ???
哈哈,你可能會(huì)像我一樣可愛,但是打印的結(jié)果不盡人意
,還是 [0, 1, 2, 3, 4, 5]
。為什么會(huì)這樣呢?
首先我們得出了一個(gè)結(jié)論,forEach不能通過(guò)return終止運(yùn)行
。
1.2 嘗試break 我們?cè)趪L試一下for
循環(huán)中的break
,看看效果會(huì)不會(huì)好一點(diǎn)。
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); // ???
結(jié)果報(bào)錯(cuò)了
:語(yǔ)法錯(cuò)誤,非法的break語(yǔ)句。
二、剖析forEach 對(duì)于上邊的結(jié)果,我很是不解,所以我們就來(lái)看一看forEach
的實(shí)現(xiàn)原理
到底是怎么樣的,我猜想萬(wàn)變不離其宗,說(shuō)到底還是for循環(huán)
。
2.1 forEach使用 const arr = [0 , 1 , 2 , 3 , 4 , 5 ]; arr.forEach((item, index, arr ) => { console .log(item, index, arr); })
遍歷的三個(gè)值分別為:值、下標(biāo)、調(diào)用方法的數(shù)組對(duì)象
。
2.2 forEach分析 我們先來(lái)看一下forEach的特點(diǎn),為此我專門去MDN [1] 上看了一下,得到了以下信息:
forEach(callbackFn)
首先接收一個(gè)回調(diào)callbackFn
,回調(diào)用三個(gè)參數(shù)(element, index, array) element
:數(shù)組中正在處理的當(dāng)前元素;index
:數(shù)組中正在處理的當(dāng)前元素的索引;array
:調(diào)用了 forEach() 的數(shù)組本身。函數(shù)沒有返回值,默認(rèn)為undefined
。 2.3 自定義myForEach 這里我把自己定義的方法寫在數(shù)組的原型上,好處就是可復(fù)用性, 根據(jù)上邊得到的信息,我們需要接收一個(gè)回調(diào)函數(shù)(fn)
,通過(guò)for循環(huán)
改變fn的this指向
,具體代碼如下: 下面我們來(lái)簡(jiǎn)單分析一下
Array .prototype.myForEach = function (fn ) { for (let i = 0 ; i < this .length; i ++) { fn.call(this , this [i], i, this ); } }
使用一下自己寫好的myForEach
看一下打印的結(jié)果
const arr = [0 , 1 , 2 , 3 , 4 , 5 ]; arr.myForEach((item, index, arr ) => { console .log(item, index, arr); })
在這里插入圖片描述 不能說(shuō)完全相同只能說(shuō)是一模一樣
。
2.4 深入解析forEach 通過(guò)2.3
我們可以看到我們的for循環(huán)中是一個(gè)函數(shù)執(zhí)行,我們最開始的寫法就是說(shuō)我們的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不能停止
。
三、改造myForEach 題外話:我這可能屬于是吃飽了沒事情做,哈哈
。
3.1 想法 試想一下,我們能不能通過(guò)改造一下我們自己定義的myForEach
方法,來(lái)達(dá)到滿足我們的要求,相信聰明的你也能夠想到,讓for循環(huán)終止
,我就簡(jiǎn)單寫一下自己的想法把,我們讓fn有返回值
,在for
循環(huán)中通過(guò)flag變量
接收。
3.2 代碼實(shí)現(xiàn) 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 } })
在這里插入圖片描述
ok!完成
四、總結(jié) 通過(guò)今天的學(xué)習(xí),相信自己以后在遇到類似的問(wèn)題一定會(huì)游刃有余。我總是強(qiáng)調(diào)基礎(chǔ)很重要,學(xué)習(xí)基礎(chǔ)也是一種美。
該文章在 2024/3/26 18:44:20 編輯過(guò)