forEach
是我們在日常工作中經(jīng)常使用到的方法,但是你有什么嘗試使用forEach
進(jìn)行停止
或終止
等操作呢?今天我就遇到了這個(gè)問題,借此來剖析一下。
一、走進(jìn)forEach 之前對于forEach
了解的并不多,只知道它可以遍歷數(shù)組,如果有這么一個(gè)操作: 一個(gè)數(shù)組[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); // ???
哈哈,你可能會像我一樣可愛,但是打印的結(jié)果不盡人意
,還是 [0, 1, 2, 3, 4, 5]
。為什么會這樣呢?
首先我們得出了一個(gè)結(jié)論,forEach不能通過return終止運(yùn)行
。
1.2 嘗試break 我們在嘗試一下for
循環(huán)中的break
,看看效果會不會好一點(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ò)了
:語法錯(cuò)誤,非法的break語句。
二、剖析forEach 對于上邊的結(jié)果,我很是不解,所以我們就來看一看forEach
的實(shí)現(xiàn)原理
到底是怎么樣的,我猜想萬變不離其宗,說到底還是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ù)組對象
。
2.2 forEach分析 我們先來看一下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)
,通過for循環(huán)
改變fn的this指向
,具體代碼如下: 下面我們來簡單分析一下
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); })
在這里插入圖片描述 不能說完全相同只能說是一模一樣
。
2.4 深入解析forEach 通過2.3
我們可以看到我們的for循環(huán)中是一個(gè)函數(shù)執(zhí)行,我們最開始的寫法就是說我們的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 想法 試想一下,我們能不能通過改造一下我們自己定義的myForEach
方法,來達(dá)到滿足我們的要求,相信聰明的你也能夠想到,讓for循環(huán)終止
,我就簡單寫一下自己的想法把,我們讓fn有返回值
,在for
循環(huán)中通過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é) 通過今天的學(xué)習(xí),相信自己以后在遇到類似的問題一定會游刃有余。我總是強(qiáng)調(diào)基礎(chǔ)很重要,學(xué)習(xí)基礎(chǔ)也是一種美。
該文章在 2024/3/26 18:44:20 編輯過