利用JS十分鐘判斷數(shù)組中存在元素的多種方式
前言
在前端開(kāi)發(fā)中,經(jīng)常會(huì)遇到要判斷數(shù)組中是否存在某個(gè)元素。其實(shí)判斷的方式有很多種,我們一個(gè)一個(gè)來(lái)了解下。
我們先來(lái)定義一個(gè)數(shù)組:
const arr = [ 13, false, 'abcd', undefined, 13, null, NaN, [1, 2], { a: 123 }, () => Date.now(), new Date('2021/03/04'), new RegExp('abc', 'ig'), Symbol('sym'), ];
在這個(gè)數(shù)組中,我們包含了好幾種類型:number, boolean, string, undefined, null, array, object, Date, Symbol 等。其中數(shù)字 13 出現(xiàn)了 2 次。
有備而來(lái)
1. indexOf
我們最熟悉的就是indexOf了,畢竟他出現(xiàn)的早,兼容性也好,使用起來(lái)也很方便。
如果存在該元素,則返回第一次出現(xiàn)的索引值;若整個(gè)數(shù)組不存在該元素,則返回-1。
1.1 使用方式
只要判斷返回的數(shù)據(jù)是不是-1,就能知道數(shù)組中是否包含該元素。
arr.indexOf(13) >= 0; // true, indexOf返回0 arr.indexOf(2) >= 0; // false, indexOf返回-1
與 indexOf 對(duì)應(yīng)的是 lastIndexOf,從最后往前查找元素,若存在該元素,則返回在數(shù)組中的最后一個(gè)的索引;若不存在該元素,則返回-1。
arr.lastIndexOf(13) >= 0; // true, lastIndexOf返回4, 最后一次出現(xiàn)的索引
兩個(gè)方法在判斷變量是否存在時(shí),調(diào)用方式是一樣的。
1.2 第 2 個(gè)可選參數(shù)
indexOf 和 lastIndexOf 還有第 2 個(gè)可選參數(shù) fromIndex,用來(lái)表示從哪個(gè)索引開(kāi)始進(jìn)行搜索。
在 indexOf 中,若 fromIndex 超過(guò)數(shù)組的長(zhǎng)度,則直接返回-1,若為負(fù)數(shù),則從最后往前數(shù)幾個(gè)索引(arr.length-Math.abs(fromIndex)),然后開(kāi)始往后搜索。
在 lastIndexOf 中,若 fromIndex 達(dá)到或超過(guò)數(shù)組的長(zhǎng)度,則搜索整個(gè)數(shù)組;若為負(fù)數(shù),則從最后往前數(shù)幾個(gè)索引(arr.length-Math.abs(fromIndex)),然后開(kāi)始往前搜索,若負(fù)數(shù)的絕對(duì)值超過(guò)了數(shù)組的長(zhǎng)度,則直接返回-1。
arr.indexOf(13, 2); // 4, 從索引值2開(kāi)始往后查找,首先找到的13的索引值為4 arr.indexOf(13, -10); // 4, 從索引值1(11-10)開(kāi)始往后檢索 arr.lastIndexOf(13, 2); // 0, 從索引值2往前開(kāi)始搜索 arr.lastIndexOf(13, -2); // 4, 從索引值9(11-2)開(kāi)始往前搜索
而且 indexOf 和 lastIndexOf 中采用的是嚴(yán)格相等的方式(===)來(lái)判斷的。
arr.indexOf(null); // 5, 在null的前面有幾個(gè)假值false和undefined,也能準(zhǔn)確找到null的索引值
瑟瑟發(fā)抖
2. includes
indexOf 主要是為了查找元素所在的索引值,只是我們可以用返回的索引值來(lái)間接判斷數(shù)組中是否存在該元素。
而在 ES7(ES2016)中添加的includes方法,就是專門用來(lái)判斷元素是否存在的。返回值為 true 或者 false,true 表示存在,false 表示不存在,簡(jiǎn)單明了。
arr.includes(13); // true arr.includes('abc'); // false arr.includes(false); // true, 存在false元素
同時(shí),includes 方法中也存在第 2 個(gè)可選參數(shù) fromIndex,fromIndex 的用法與 indexOf 中的一樣。若 fromIndex 超過(guò)數(shù)組的長(zhǎng)度,則直接返回-1,若為負(fù)數(shù),則從最后往前數(shù)幾個(gè)索引(arr.length-Math.abs(fromIndex)),然后開(kāi)始往后搜索。
arr.includes(13, 5); // false, 從索引值5開(kāi)始往后檢索,沒(méi)檢索到
到目前為止,后面的幾種類型,例如 Array, Object, Date 和 Symbol,我們都沒(méi)判斷呢。我們現(xiàn)在來(lái)判斷下后面的幾個(gè)元素:
// 使用indexOf判斷 arr.indexOf(NaN); // -1 arr.indexOf([1, 2]); // -1 arr.indexOf({ a: 123 }); // -1 arr.indexOf(() => Date.now()); // -1 arr.indexOf(new Date('2021/03/04')); // -1 arr.indexOf(new RegExp('abc', 'ig')); // -1 arr.indexOf(Symbol('sym')); // -1 // 使用includes判斷 arr.includes(NaN); // false arr.includes([1, 2]); // false arr.includes({ a: 123 }); // false arr.includes(() => Date.now()); // false arr.includes(new Date('2021/03/04')); // false arr.includes(new RegExp('abc', 'ig')); // false arr.includes(Symbol('sym')); // false
結(jié)局很慘,這幾種元素在數(shù)組中都沒(méi)有檢索到??墒菍?shí)際上在數(shù)組中都是真實(shí)存在的。
這是因?yàn)?indexOf 和 includes 都是采用嚴(yán)格相等的方式(===)來(lái)判定的。
NaN === NaN; // false, 兩個(gè)NaN永遠(yuǎn)也不會(huì)相等 [1, 2] === [1, 2]; // false, 每個(gè)聲明出來(lái)的數(shù)組都有單獨(dú)的存儲(chǔ)地址 {a: 123} === {a: 123}; // false, 同數(shù)組 new Date('2021/03/04')===new Date('2021/03/04'); // false, 看著日期是相同的,但是用new出來(lái)的對(duì)象進(jìn)行比較的,肯定是不相等的 Symbol('sym')===Symbol('sym'); // Symbol類型的出現(xiàn)就是為了避免沖突創(chuàng)造出來(lái)的類型,括號(hào)里的屬性僅是為了方便描述而已
針對(duì)這些無(wú)法被檢索的類型,我們就需要自己寫函數(shù)來(lái)判斷特殊的類型了。
3. find 和 findIndex
find()和 findIndex()允許我們通過(guò)回調(diào)函數(shù),來(lái)自定義判斷的方式。
3.1 find 方法
find() 方法返回?cái)?shù)組中滿足提供的測(cè)試函數(shù)的第一個(gè)元素的值。否則返回 undefined。
find()方法無(wú)法檢測(cè)數(shù)組中的 undefined 元素。
因?yàn)椴淮嬖诤痛嬖?undefined 元素,find()方法都會(huì)返回 undefined。這里我們就要考慮其他方式了,稍后再講。
arr.find((item) => item === 13); // 13, 找到了元素13 arr.find((item) => item === 3); // undefined, 沒(méi)找到元素3 arr.find((item) => item === undefined); // undefined, 也不知道是找到了還是沒(méi)找到
對(duì)于上面稍微復(fù)雜點(diǎn)的類型,我們就需要特殊的判斷了:
arr.find((item) => typeof item === 'number' && isNaN(item)); // NaN // array和object類型進(jìn)行比較時(shí),情況很復(fù)雜,因?yàn)槊總€(gè)元素的類型都無(wú)法確定 // 如果確定都是基本類型,如string, number, boolean, undefined, null等,可以將其轉(zhuǎn)為字符串再比較 // 轉(zhuǎn)字符串的方式也很多,如JSON.stringify(arr), arr.toString(), arr.split('|')等 // 復(fù)雜點(diǎn)的,只能一項(xiàng)一項(xiàng)比較,或者使用遞歸 arr.find((item) => item.toString() === [1, 2].toString()); // [1, 2] arr.find((item) => JSON.stringify(item) === JSON.stringify({ a: 123 })); // {a: 123} arr.find((item) => { if (typeof item === 'function') { return item.toString() === (() => Date.now()).toString(); } return false; }); // () => Date.now() arr.find((item) => { if (item instanceof Date) { return item.toString() === new Date('2021/03/04').toString(); } return false; }); // Thu Mar 04 2021 00:00:00 GMT+0800 arr.find((item) => { if (item instanceof RegExp) { return item.toString() === new RegExp('abc', 'ig').toString(); } return false; }); // /abc/gi // Symbol確實(shí)沒(méi)法比較,只能比較描述是否一樣 arr.find((item) => { if (typeof item === 'symbol') { return item.toString() === Symbol('sym').toString(); } return false; }); // Symbol(sym)
上面的判斷代碼在后面的方法也將會(huì)使用到。
3.2 兩個(gè)元素進(jìn)行比較
我們?cè)谏厦鎸?duì)比了多種類型元素的比較,稍微來(lái)總結(jié)下。
先來(lái)定義一個(gè)函數(shù):
const compare = (x, y) => {};
3.2.1 基本類型
對(duì)于元素是 string, number, boolean, undefined, null 等基本類型的,可以直接進(jìn)行比較:
const compare = (x, y) => { return x === y; };
3.2.2 NaN 數(shù)據(jù)
NaN 用 typeof 來(lái)判斷是 number 類型,但 NaN 不與任何數(shù)字相等,包括它自己。
const compare = (x, y) => { if (typeof x === 'number' && isNaN(x) && typeof y === 'number' && isNaN(y)) { return true; } return x === y; };
3.2.3 Function 與 Date 與 RegExp
這些類型的,可以將變量轉(zhuǎn)為字符串進(jìn)行比較:
const compare = (x, y) => { if (typeof x === 'number' && isNaN(x) && typeof y === 'number' && isNaN(y)) { return true; } if ( (typeof x === 'function' && typeof y === 'function') || (x instanceof Date && y instanceof Date) || (x instanceof RegExp && y instanceof RegExp) || (x instanceof String && y instanceof String) || (x instanceof Number && y instanceof Number) ) { return x.toString() === y.toString(); } return x === y; };
對(duì)于 object 類型和 array 的,我們可以將每一項(xiàng)拆開(kāi),然后利用上面的方式再挨個(gè)兒比較。
3.3 findIndex 方法
如果還要判斷數(shù)組中是否存在 undefined,我們可以使用findIndex()方法。
findIndex() 方法返回?cái)?shù)組中滿足提供的測(cè)試函數(shù)的第一個(gè)元素的索引。若沒(méi)有找到對(duì)應(yīng)元素則返回-1。
arr.findIndex((item) => item === undefined); // 3 arr.findIndex((item) => item === 3); // -1, 沒(méi)有找到數(shù)字3
其他數(shù)據(jù)格式的判斷,與上面的 find()一樣。
稀客呀
4. some
some() 方法測(cè)試數(shù)組中是不是至少有 1 個(gè)元素通過(guò)了被提供的函數(shù)測(cè)試。它返回的是一個(gè) Boolean 類型的值。
注意:如果用一個(gè)空數(shù)組進(jìn)行測(cè)試,在任何情況下它返回的都是 false。
some()方法與 find()方法的使用方式一樣,只不過(guò) some()方法返回的是 boolean 類型的數(shù)據(jù)。
arr.some((item) => item === false); // true arr.some((item) => item === undefined); // true arr.some((item) => typeof item === 'number' && isNaN(item)); // true arr.some((item) => item === 3); // false, 不存在數(shù)字3 arr.some((item) => { if (item instanceof Date) { return item.toString() === new Date('2021/03/04').toString(); } return false; }); // true
5. filter
filter() 方法創(chuàng)建一個(gè)新數(shù)組, 其包含通過(guò)所提供函數(shù)實(shí)現(xiàn)的測(cè)試的所有元素。
無(wú)論找到幾個(gè)元素或者沒(méi)有元素,filter()方法都是會(huì)返回一個(gè)數(shù)組,數(shù)組中的數(shù)據(jù)就是我們想要的元素。
arr.filter((item) => item === false); // 1 arr.filter((item) => item === undefined); // 1 arr.filter((item) => typeof item === 'number' && isNaN(item)); // 1 arr.filter((item) => item === 13); // 2 arr.filter((item) => item === 3); // 0 arr.filter((item) => { if (item instanceof Date) { return item.toString() === new Date('2021/03/04').toString(); } return false; }); // 1
因此我們可以通過(guò)該數(shù)組的長(zhǎng)度,來(lái)判斷原數(shù)組是否包含我們想要的元素。
略略
6. 總結(jié)
查找數(shù)組中元素的方式有很多,我們可以數(shù)組中元素的格式,來(lái)選擇更合適的方式。如果都是一些基本類型,建議優(yōu)先選擇使用includes()方法;如果格式比較復(fù)雜的,建議選擇使用some()方法。這兩個(gè)方法都是直接返回 boolean 類型,無(wú)需更多的轉(zhuǎn)換即可直接使用方法的結(jié)果。
到此這篇關(guān)于利用JS十分鐘判斷數(shù)組中存在元素的多種方式的文章就介紹到這了,更多相關(guān)JS判斷數(shù)組存在元素內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JS判斷數(shù)組里是否有重復(fù)元素的方法小結(jié)
- JavaScript判斷數(shù)組是否包含指定元素的方法
- JS判斷元素是否在數(shù)組內(nèi)的實(shí)現(xiàn)代碼
- JS判斷數(shù)組是否包含某元素實(shí)現(xiàn)方法匯總
- JS實(shí)現(xiàn)判斷數(shù)組是否包含某個(gè)元素示例
- 判斷數(shù)組是否包含某個(gè)元素的js函數(shù)實(shí)現(xiàn)方法
- javascript 判斷數(shù)組是否已包含了某個(gè)元素的函數(shù)
- javascript如何判斷數(shù)組內(nèi)元素是否重復(fù)的方法集錦
- 利用JS判斷元素是否為數(shù)組的方法示例
- JS判斷元素是否存在數(shù)組中的5種方式總結(jié)
相關(guān)文章
cordova入門基礎(chǔ)教程及使用中遇到的一些問(wèn)題總結(jié)
這篇文章主要給大家介紹了關(guān)于cordova的入門基礎(chǔ)教程以及在使用中遇到的一些問(wèn)題,文中通過(guò)示例代碼一步步介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11Web js實(shí)現(xiàn)復(fù)制文本到粘貼板
這篇文章主要為大家詳細(xì)介紹了Web js實(shí)現(xiàn)復(fù)制文本到粘貼板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08JS實(shí)現(xiàn)的仿淘寶交易倒計(jì)時(shí)效果
這篇文章主要介紹了JS實(shí)現(xiàn)的仿淘寶交易倒計(jì)時(shí)效果,涉及JavaScript針對(duì)時(shí)間與日期的動(dòng)態(tài)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11原生js實(shí)現(xiàn)ajax請(qǐng)求和JSONP跨域請(qǐng)求操作示例
這篇文章主要介紹了原生js實(shí)現(xiàn)ajax請(qǐng)求和JSONP跨域請(qǐng)求操作,結(jié)合實(shí)例形式分析了基于原生js實(shí)現(xiàn)的ajax請(qǐng)求和JSONP跨域請(qǐng)求相關(guān)操作技巧與使用注意事項(xiàng),需要的朋友可以參考下2020-03-03