1. 程式人生 > 程式設計 >利用JS十分鐘判斷陣列中存在元素的多種方式

利用JS十分鐘判斷陣列中存在元素的多種方式

前言

在前端開發中,經常會遇到要判斷陣列中是否存在某個元素。其實判斷的方式有很多種,我們一個一個來了解下。

我們先來定義一個數組:

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'),];

在這個陣列中,我們包含了好幾種類型:number,boolean,string,array,object,Date,Symbol 等。其中數字 13 出現了 2 次。

有備而來

1. indexOf

我們最熟悉的就是indexOf了,畢竟他出現的早,相容性也好,使用起來也很方便。

如果存在該元素,則返回第一次出現的索引值;若整個陣列不存在該元素,則返回-1。

1.1 使用方式

只要判斷返回的資料是不是-1,就能知道陣列中是否包含該元素。

arr.indexOf(13) >= 0; // true,indexOf返回0
arr.indexOf(2) >= 0; // false,indexOf返回-1

與 indexOf 對應的是 lastIndexOf,從最後往前查詢元素,若存在該元素,則返回在陣列中的最後一個的索引;若不存在該元素,則返回-1。

arr.lastIndexOf(13) &www.cppcns.comgt;= 0; // true,lastIndexOf返回4,最後一次出現的索引

兩個方法在判斷變數是否存在時,呼叫方式是一樣的。

1.2 第 2 個可選引數

indexOf 和 lastIndexOf 還有第 2 個可選引數 fromIndex,用來表示從哪個索引開始進行搜尋。

在 indexOf 中,若 fromIndex 超過陣列的長度,則直接返回-1,若為負數,則從最後往前數幾個索引(arr.length-Math.abs(fromIndex)),然後開始往後搜尋。

在 lastIndexOf 中,若 fromIndex 達到或超過陣列的長度,則搜尋整個陣列;若為負數,則從最後往前數幾個索引(arr.length-Math.abs(fromIndex)),然後開始往前搜尋,若負數的絕對值超過了陣列的長度,則直接返回-1。

arr.indexOf(13,2); // 4,從索引值2開始往後查詢,首先找到的13的索引值為4http://www.cppcns.com
arr.indexOf(13,-10); // 4,從索引值1(11-10)開始往後檢索
arr.lastIndexOf(13,2); // 0,從索引值2往前開始搜尋
arr.lastIndexOf(13,-2); // 4,從索引值9(11-2)開始往前搜尋

而且 indexOf 和 lastIndexOf 中採用的是嚴格相等的方式(===)來判斷的。

arr.indexOf(null); // 5,在null的前面有幾個假值false和undefined,也能準確找到null的索引值
瑟瑟發抖

2. includes

indexOf 主要是為了查詢元素所在的索引值,只是我們可以用返回的索引值來間接判斷陣列中是否存在該元素。

而在 ES7(ES2016)中新增的includes方法,就是專門用來判斷元素是否存在的。返回值為 true 或者 false,true 表示存在,false 表示不存在,簡單明瞭。

arr.includes(13); // true
arr.includes('abc'); // false
arr.includes(false); // true,存在false元素

同時,includes 方法中也存在第 2 個可選引數 fromIndex,fromIndex 的用法與 indexOf 中的一樣。若 fromIndex 超過陣列的長度,則直接返回-1,若為負數,則從最後往前數幾個索引(arr.length-Math.abs(fromIndex)),然後開始往後搜尋。

arr.includes(13,5); // false,從索引值5開始往後檢索,沒檢索到

到目前為止,後面的幾種型別,例如 Array,Object,Date 和 Symbol,我們都沒判斷呢。我們現在來判斷下後面的幾個元素:

// 使用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(SymboHgjsoyl('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

結局很慘,這幾種元素在陣列中都沒有檢索到。可是實際上在陣列中都是真實存在的。

這是因為 indexOf 和 includes 都是採用嚴格相等的方式(===)來判定的。

NaN === NaN; // false,兩個NaN永遠也不HgJSoy會相等
[1,2] === [1,2]; // false,每個宣告出來的陣列都有單獨的儲存地址
{a: 123} === {a: 123}; // false,同陣列
new Date('2021/03/04')===new Date('2021/03/04'); // false,看著日期是相同的,但是用new出來的物件進行比較的,肯定是不相等的
Symbol('sym')===Symbol('sym'); // Symbol型別的出現就是為了避免衝突創造出來的型別,括號裡的屬性僅是為了方便描述而已

針對這些無法被檢索的型別,我們就需要自己寫函式來判斷特殊的型別了。

3. find 和 findIndex

find()和 findIndex()允許我們通過回撥函式,來自定義判斷的方式。

3.1 find 方法

find() 方法返回陣列中滿足提供的測試函式的第一個元素的值。否則返回 undefined。

find()方法無法檢測陣列中的 undefined 元素。

因為不存在和存在 undefined 元素,find()方法都會返回 undefined。這裡我們就要考慮其他方式了,稍後再講。

arr.find((item) => item === 13); // 13,找到了元素13
arr.find((item) => item === 3http://www.cppcns.com); // undefined,沒找到元素3
arr.find((item) => item === undefined); // undefined,也不知道是找到了還是沒找到

對於上面稍微複雜點的型別,我們就需要特殊的判斷了:

arr.find((item) => typeof item === 'number' && isNaN(item)); // NaN

// array和object型別進行比較時,情況很複雜,因為每個元素的型別都無法確定
// 如果確定都是基本型別,如string,number,null等,可以將其轉為字串再比較
// 轉字串的方式也很多,如JSON.stringify(arr),arr.toString(),arr.split('|')等
// 複雜點的,只能一項一項比較,或者使用遞迴
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確實沒法比較,只能比較描述是否一樣
arr.find((item) => {
 if (typeof item === 'symbol') {
 return item.toString() === Symbol('sym').toString();
 }
 return false;
}); // Symbol(sym)

上面的判斷程式碼在後面的方法也將會使用到。

3.2 兩個元素進行比較

我們在上面對比了多種型別元素的比較,稍微來總結下。

先來定義一個函式:

const compare = (x,y) => {};

3.2.1 基本型別

對於元素是 string,null 等基本型別的,可以直接進行比較:

const compare = (x,y) => {
 return x === y;
};

3.2.2 NaN 資料

NaN 用 typeof 來判斷是 number 型別,但 NaN 不與任何數字相等,包括它自己。

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

這些型別的,可以將變數轉為字串進行比較:

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;
};

對於 object 型別和 array 的,我們可以將每一項拆開,然後利用上面的方式再挨個兒比較。

3.3 findIndex 方法

如果還要判斷陣列中是否存在 undefined,我們可以使用findIndex()方法。

findIndex() 方法返回陣列中滿足提供的測試函式的第一個元素的索引。若沒有找到對應元素則返回-1。

arr.findIndex((item) => item === undefined); // 3
arr.findIndex((item) => item === 3); // -1,沒有找到數字3

其他資料格式的判斷,與上面的 find()一樣。

稀客呀

4. some

some() 方法測試陣列中是不是至少有 1 個元素通過了被提供的函式測試。它返回的是一個 Boolean 型別的值。

注意:如果用一個空陣列進行測試,在任何情況下它返回的都是 false。

some()方法與 find()方法的使用方式一樣,只不過 some()方法返回的是 boolean 型別的資料。

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,不存在數字3
arr.some((item) => {
 if (item instanceof Date) {
  return item.toString() === new Date('2021/03/04').toString();
 }
 return false;
}); // true

5. filter

filter() 方法建立一個新陣列,其包含通過所提供函式實現的測試的所有元素。

無論找到幾個元素或者沒有元素,filter()方法都是會返回一個數組,陣列中的資料就是我們想要的元素。

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

因此我們可以通過該陣列的長度,來判斷原陣列是否包含我們想要的元素。

略略

6. 總結

查詢陣列中元素的方式有很多,我們可以陣列中元素的格式,來選擇更合適的方式。如果都是一些基本型別,建議優先選擇使用includes()方法;如果格式比較複雜的,建議選擇使用some()方法。這兩個方法都是直接返回 boolean 型別,無需更多的轉換即可直接使用方法的結果。

到此這篇關於利用JS十分鐘判斷陣列中存在元素的多種方式的文章就介紹到這了,更多相關JS判斷陣列存在元素內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!