iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 27
1
Day 27

那一排,都是穿黑衣戴口罩的,去幫我找出搗亂的。抱歉,我只能給你 -1 因為連我們偶爾都會穿黑衣戴口罩。

終於,我們要進入ECMAScript 5 的陣列方法了!
ECMAScript 5 定義了許多很重要的陣列方法,包括了過濾、檢測、遍歷、搜索和鏡射的方法,讓我們能更輕易的操控陣列與陣列元素。

但是今天是週末,我們先來介紹相對比較沒那麼複雜的indexOf()

indexOf()方法像是一個會通風報信的吹哨人,請它去幫忙找出陣列裡面的某個指定元素,它就會 明查暗訪 幫我們把這個元素找出來,並告訴我們這個元素在哪個位置(索引值),它只會給我們「第一個」找到的位置 表示有交差,如果沒有找到,indexOf()就會回傳給我們 -1 表示在陣列裡找不到這個元素。

Array.prototype.indexOf() - JavaScript | MDN

陣列處理方法集合

原型: Array.prototype.indexOf()
功能: 搜尋陣列中指定的值。
改變: 不會改變原陣列。
語法: arr.indexOf(searchElement[, fromIndex])
回傳值: 在陣列中找到的第一個元素索引值;沒找到則為 -1。
參數: 要找的元素、從哪裡開始找。

為了不混淆,我們以字串元素來示範

const arr = ["a", "b", "c", "D", "C", "b", "a"];

// 沒給參數,不知道我們要找的元素是什麼,回傳 -1 很合理。
arr.indexOf(); // -1

// 找到的 "c" 在索引值 2 的位置
arr.indexOf("c"); // 2

// 從索引值 2 的位置開始找,所以找到第二個 "b"
arr.indexOf("b", 2); // 5

// 從索引值 3 的位置開始找,會區分大小寫,找不到 "c" 回傳 -1
arr.indexOf("c", 3); // -1

// 第二參數預設就是 0 ,這裡有寫沒寫都ㄧ樣
arr.indexOf("c", 0); // 2

// 第二參數 -5 表示從後面數過來 -5 的位置開始找,所以找得到 "c"
arr.indexOf("c", -5); // 2

// 但是從 -5 開始找就找不到"c" 所以回傳 -1
arr.indexOf("c", -4); // -1

參數的規則很直覺

indexOf()可帶兩個參數,第一個參數searchElement是指定要找尋的元素,第二個參數fromIndex索引值,不是必須,表示要從哪一個位置開始搜尋。如果這個索引值大於或等於陣列的長度,會直接回傳 -1,因為要開始搜尋的元素都已經超過陣列長度,自然搜尋就起不了作用。

如果給的fromIndex索引值是一個負數,就會從陣列的最後一個往回算,等同最後一個的索引值是 -1,以此類推。

雖然表示往回算,但indexOf()的搜尋順序依然會從陣列的左往右一一搜尋。如果負數索引值在回頭計算之後仍然小於 0,則會從左往右全部搜尋。

這個參數的預設值為 0(即搜尋整個陣列)。還有,indexOf()並不像其他大部分的ECMAScript 5 陣列方法一樣,參數可以帶函式,帶函式參數對indexOf()是無效的。

找出所有陣列裡指定的索引值

雖然indexOf()只會回傳給我們第一個找到的元素位置,但是我們可以使用迴圈,將陣列裡面所有符合搜尋條件元素的索引值,放在一個陣列裡:

function findAll(arr,element){
  const results = [];
  let len = arr.length;
  let fromIndex = 0;
  while(fromIndex < len){
    fromIndex = arr.indexOf(element, fromIndex);
    if(fromIndex === -1) break; // 沒找到完成搜尋
    results.push(fromIndex); // 將找到的索引值放入陣列
    fromIndex = fromIndex + 1;
  }
  return results;
}

let result = findAll(arr,"b")
result; // [1, 5]

如果可以將找到的索引位置的值,集中放入陣列裡是不是更方便?indexOf()雖然無法直接做到,但是有其他方法可以做到這些,例如 ECMAScript 5 的filter或 ECMAScript 6 的find()都可以輕易辦到。

參考型別的元素找法

和某些部分陣列的方法ㄧ樣,indexOf()是無法直接查找參考型別的元素,像是陣列、物件,需要將這些元素指定給一個變數,這個變數在陣列裡,就可使用indexOf()到。

const arr2 = ["a", {a:42} ]

arr2.indexOf("a"); // 0 找得到
arr2.indexOf({a:42}); // -1 找不到

// 將元素指定給變數
const arr = [1,2];
const arr3 = [42, arr ]
arr3.indexOf(arr); // 1 

const obj = {a:42}
const arr4 = ["a", obj, 12]
arr4.indexOf(obj); // 1

其實,還有另一個indexOf()的孿生陣列方法lastIndexOf()功能和indexOf()差不多 簡直ㄧ樣,我們明天可以來聊聊,順便穿插一些輕鬆題外話~敬請期待囉~

才剛要介紹 ECMAScript 5 的陣列方法,鐵人賽就快要結束了,那 ECMAScript 6 呢? 不長進的留到明年寫嗎? 參加鐵人賽所獲得的,也不只是介紹這些方法而已。因鐵人賽讓本人開始了解查找資料的樂趣 大嬸瘋了 所以,應該會繼續不定期寫下去喔~

如有需要改進的地方,拜託懇求請告知,我會盡量快速度修改,感謝您~

開頭的那句開場白,寫的時候有點心驚驚,會不會太敏感、會不會太表明立場?所謂民主,應該是不需要懼怕這些的,所謂民主,應該是可以讓人們自由的發表言論而不被壓抑,民主的另一種姿態是勇敢,勇敢捍衛這些得來不易的自由。 這些絕對不是要湊字數XD

上一篇
JS 把陣列 Array 轉成字串與本地化的 toLocaleString()
下一篇
JS 陣列 Array 方法,找出最後一個元素的索引值 lastIndexOf()
系列文
JavaScript之一定要了解的 Array 與方法32

1 則留言

0
huli
iT邦新手 5 級 ‧ 2019-10-12 12:51:07

最後提的:「參考型別的元素無法找」,我覺得有些奇怪
不是沒辦法找,是照原文中那樣子不可能找到

對 indexOf 這個方法來說,無論你找什麼都是沒差的
都只是在比較 array 裡面是否有元素 === 你要找的東西
原文的例子要找的 {a:42} 跟 arr 裡面的 {a:42} 位置不同,自然不會相等
換成底下這樣就找得到了:

const obj = {a:42}
const arr = [0, 1, 2, obj]
console.log(arr.indexOf(obj)) //3
tsuifei iT邦新手 5 級‧ 2019-10-12 18:36:26 檢舉

原來可以這樣用,我都沒想到!太感謝胡大了!
晚點來修改。

我要留言

立即登入留言