iT邦幫忙

2021 iThome 鐵人賽

DAY 3
1
Modern Web

Javascript 從寫對到寫好系列 第 3

Day 3 - Array 陣列組合技 (2)

前言

前一篇介紹了 forEachfiltermapreduce,算是平常我比較常使用,而且在很多情況可以通用的陣列組合技了。

今天來講的,是比較針對特定情境的功能,會在很多腦袋卡住的時候突然「啊哈!」想到的 method。

各種 Method 的實戰

今天來看看以下這幾個 array 常用的 method:

  • includes / indexOf / splice
  • some / every
  • sort

includes / indexOf / splice

includes() 方法會判斷陣列是否包含特定的元素,並以此來回傳 true 或 false。(參考 MDN)

arr.includes(searchElement[, fromIndex])

indexOf() 方法會回傳給定元素於陣列中第一個被找到之索引,若不存在於陣列中則回傳 -1。(參考 MDN)

arr.indexOf(searchElement[, fromIndex])

splice() 方法可以藉由刪除既有元素並/或加入新元素來改變一個陣列的內容。(參考 MDN)

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

這組 combo 帶有一種「針對某個人」的感覺(霸凌?)

  • includes:單純用來判斷是否包含某個人
  • indexOf:不只判斷是否包含某個人,還找到在哪個位置
  • splice:可以在指定位置新增或刪掉某個人

✔ Checkbox 勾選


實戰上可以應用在表單內的 checkbox,我們會自己保存一個 checked 的陣列,代表有勾選的項目。

當我們點擊原本不在陣列中的東西時,會透過 includes 發現並用 push 加進去;反之,如果原本就在陣列中,會透過 indexOf 找到是在哪個位置,接著用 splice 將該位置抽掉。

const checked = [?, ?, ?];

const onChanged = (item) => {
    if (checked.includes(item)) {
        const itemIndex = checked.indexOf(item);
        checked.splice(itemIndex, 1);
    } else {
        checked.push(item);
    }
};

console.log(checked); // [?, ?, ?]

// 這邊模擬點擊的效果
onChanged(?);
console.log(checked); // [?, ?]
onChanged(?);
console.log(checked); // [?, ?, ?]

✅ some / every

some() 方法會透過給定函式、測試陣列中是否至少有一個元素,通過該函式所實作的測試。(參考MDN)

arr.some(callback[, thisArg])

every() 方法會測試陣列中的所有元素是否都通過了由給定之函式所實作的測試。(參考MDN)

arr.every(callback[, thisArg])

原本用 for 迴圈會搭配 break 來提升效率,但如果只是單純用迴圈來做判斷,使用 some()every() 可以用更少的 code 做到一樣的事情,並且提升可讀性。

兩者的差異:

  • some(): 陣列中至少一個符合就回傳 true
  • every(): 陣列中至少一個符合就回傳 false

題外話,這對組合真的很像太極上面的黑與白啊!

✔ 用 some() 判斷「檢核錯誤」

const fields = [
    { name: 'Allen', error: false },
    { password: 'Gx45Fa', error: false },
    { email: 'abcdgmail.com', error: true },
    { phone: '0912345678', error: false }
];
// 只要任何一個欄位有 error,整體而言就是錯誤
const invalid = fields.some(field => field.error);
// 可以改用 every() 反向來寫,但這個 case 用 some() 比較好讀
const invalid2 = !fields.every(field => !field.error);

if (invalid) {
    console.log('請檢查欄位是否正確');
}

執行結果

請檢查欄位是否正確

✔ 用 every() 判斷是否「全選」

const options = [
    { icon: ?, checked: true },
    { icon: ?, checked: true },
    { icon: ?, checked: false },
    { icon: ?, checked: true }
];
let allChecked = false;

const onChanged = (item) => {
    const foundOption = options.find(option => option.icon === item);
    foundOption.checked = !foundOption.checked;
    
    // 每個選項都有勾選的話,就可以讓「全選」勾選
    allChecked = options.every(option => option.checked);
    // 可以改用 some() 反向來寫,但這個 case 用 every() 比較好讀
    allChecked = !options.some(option => !option.checked);
    
    if (allChecked) {
        console.log('全選!');
    }
};

// 這邊模擬點擊的效果
onChanged(?);

執行結果

全選!

✅ sort

sort() 方法會原地(in place)對一個陣列的所有元素進行排序,並回傳此陣列。(參考 MDN)

arr.sort([compareFunction])

sort 的用法很單純,就是排序。但因為可以帶一個 function 當作參數,就能夠做到複雜,甚至客製化的排序:

✔ 基礎版(不帶參數,根據 Unicode 排序)

const arr = ['Jack', 'Allen', 'Alice', 'Susan'];
arr.sort();
console.log(arr);

執行結果

["Alice", "Allen", "Jack", "Susan"]

✔ Array of object 排序(指定 property)

可以直接拿陣列裡每個 object 中的指定 property 來排序,會需要幫 sort 帶一個函式當參數,如果是 number,可以回傳相減的結果,因為回傳正、負數會讓排序結果不同。

const arr = [
    { name: 'Jack', score: 70 },
    { name: 'Allen', score: 50 },
    { name: 'Alice', score: 60 },
    { name: 'Susan', score: 90 }
];
// 升幂 用 a.score - b.score
// 降幂 用 b.score - a.score
arr.sort((a, b) => a.score - b.score);
console.log(arr); 

執行結果

[
    { name: 'Allen', score: 50 },
    { name: 'Alice', score: 60 },
    { name: 'Jack', score: 70 },
    { name: 'Susan', score: 90 }
]

✔ 指定排序順序(搭配 indexOf())

indexOf 是 array 的其中一個 method,可以搜尋指定子元素在陣列中的索引(index),若找不到則回傳 -1,詳細可參考 MDN

這種比較會用在,存資料的時候沒有按照順序,但顯示資料時卻要按照指定的順序

const arr = [
    { name: 'Jack', score: 70 },
    { name: 'Allen', score: 50 },
    { name: 'Alice', score: 60 },
    { name: 'Susan', score: 90 }
];
// 指定排序順序要按照這樣
const arrOrder = ['Susan', 'Allen', 'Jack', 'Alice'];

arr.sort((a, b) => (arrOrder.indexOf(a.name) < arrOrder.indexOf(b.name) ? -1 : 1));

console.log(arr); 

執行結果

[
    { name: 'Susan', score: 90 },
    { name: 'Allen', score: 50 },
    { name: 'Jack', score: 70 },
    { name: 'Alice', score: 60 }
];

結語

array 還有非常多好用的 method 可以用,可以參考 MDN,雖然用法我們都看得懂,但實戰才是最重要的(跟考駕照一樣?),而這些通常也不會有人特地寫文章介紹,而是要從長年看 code、用 code 的過程中體驗,並且把好的使用情境記下來。

因此如果有機會看到其他人寫的 code,真的是有很多地方可以觀摩學習,而且通常要搭配情境(context)比較好理解,才會在寫 code 的過程中信手拈來。

漫天星點
在每一個連結與跨越
化作指引的星輝

參考資料

Array MDN


上一篇
Day 2 - Array 陣列組合技 (1)
下一篇
Day 4 - Object 物件組合技
系列文
Javascript 從寫對到寫好30

2 則留言

1
pjchender
iT邦新手 4 級 ‧ 2021-09-19 01:25:21

舉的例子都好實用喔!

1
Ken Chen
iT邦新手 5 級 ‧ 2021-09-19 01:40:27

感謝分享~
很棒的歸納耶

我要留言

立即登入留言