巧技拾遺 | JavaScript 中 Array.every 和 Array.map 的巧妙結(jié)合
這幾天在跟著學(xué)一點(diǎn) vue3 + TypeScript 中表單驗(yàn)證的實(shí)例,看到一個(gè)實(shí)現(xiàn),覺(jué)得非常巧妙。
需求概述
我們有一個(gè)列表 funcArr ,里面存放函數(shù),比如 funcArr = [ func1, func2, ... ] 。這些函數(shù)都是 () => boolean 即無(wú)參數(shù)、返回值為布爾值的。
我們期望在提交表單時(shí),執(zhí)行 funcArr 中的每一個(gè)函數(shù),如果這些函數(shù)都通過(guò)驗(yàn)證,則我們的主邏輯獲取到 true ,否則是 false 。
樸素版本
- func1 = () => { console.log(1); return true; }
- func2 = () => { console.log(2); return false; }
- func3 = () => { console.log(3); return true; }
- funcArr = [func1, func2, func3];
- result = true;
- for (var i = 0; i < funcArr.length; i ++ )
- {
- if (!funcArr[i]( "i")) result = false;
- }
- console.log(result)
輸出是:
- > 1
- > 2
- > 3
- > false
這種做法顯然有點(diǎn)瞎扯了,完全沒(méi)有用到 JavaScript 特性和函數(shù)式編程的思想。
Array.prototype.every()
一般來(lái)講,有上述需求,我們用 Array.prototype.every()[1] 函數(shù)來(lái)解決。
根據(jù) MDN 的描述:every用于檢測(cè)是否每個(gè)函數(shù)都通過(guò),并且最終返回 一個(gè) 布爾值。
于是:
- func1 = () => { console.log(1); return true; }
- func2 = () => { console.log(2); return false; }
- func3 = () => { console.log(3); return true; }
- funcArr = [func1, func2, func3];
- result = funcArr.every(func => func());
- console.log(result)
輸出:
- > 1
- > 2
- > false
可以注意到一個(gè)現(xiàn)象:當(dāng)every發(fā)現(xiàn)有一個(gè)元素沒(méi)有通過(guò)驗(yàn)證時(shí),它就不再繼續(xù)檢查其他元素了。
結(jié)合 map()
有時(shí)候,我們的 funcArr 中的函數(shù),不僅僅是單純的返回一個(gè)布爾值,其中還有其他邏輯如修改一些響應(yīng)式變量的作用。
因此,我們希望 every 能夠執(zhí)行完畢所有函數(shù),即便發(fā)現(xiàn)其中某一個(gè)是 return false 了的。
考慮使用 map 。
- func1 = () => { console.log(1); return true; }
- func2 = () => { console.log(2); return false; }
- func3 = () => { console.log(3); return true; }
- funcArr = [func1, func2, func3];
- result = funcArr.map(func => func()).every(res => res);
- console.log(result)
輸出:
- > 1
- > 2
- > 3
- > false
every在其中的作用,像是一個(gè)漏斗,把所有的值依次過(guò)濾,有一個(gè) false 就返回 false ,否則是 true 。