前言
今天来讲的,是比较针对特定情境的功能,会在很多脑袋卡住的时候突然「啊哈!」想到的 method。
各种 Method 的实战
今天来看看以下这几个 array 常用的 method:
includes/indexOf/splicesome/everysort
✅ 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(): 阵列中至少一个符合就回传 trueevery(): 阵列中至少一个不符合就回传 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);
✔ 指定排序顺序 (搭配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 的过程中信手拈来。