JavaScript 数组的 20 个最常见用例
拼接、切片、弹出和移位。数组排序方法稳定且不就地吗?记住所有 JavaScript 数组方法以及它们之间的区别并不容易。它们都是同义词,就像直接从同义词库中摘录的一样。
这份数组速查表列出了 JavaScript 中所有常用的数组方法,而那些你不需要的方法则不在这里。就这么简单!为了方便你理解,我根据常见的用例制作了这份速查表。
不变性
开始之前,先说一下不可变性。本文中使用的所有函数都是immutable 的,简而言之,当你使用这些方法时,你永远不会改变原始数组。不可变性在现代 JavaScript 中非常重要,至少Stack Overflow 上(以及互联网上)的其他人都这么认为。
尽管这些方法本身都是不可变的,但你并不能完全避免不可变性。如果你在不可变数组中包含可变数据类型(数组、对象、函数),你仍然可以修改数组中的可变数据。我们称这样的数组为浅不可变数组,与仅包含不可变项的深不可变数组相对。
数组用例
- 将元素添加到数组的开头
- 将元素添加到数组末尾
- 从数组开头删除一个元素
- 从数组末尾删除一个元素
- 在数组的索引处插入元素
- 替换数组中索引处的元素
- 删除数组中索引处的元素
- 根据值从数组中删除元素
- 根据属性从数组中删除对象
- 检查数组是否包含元素
- 检查数组是否包含具有属性的对象
- 检查数组中的所有对象是否都具有某个属性
- 将数组转换为对象
- 将对象数组转换为对象
- 将对象转换为数组
- 合并两个数组
- 对数组进行排序
- 对对象数组进行排序
- 反转数组
- 从数组中删除重复项
1. 将元素添加到数组的开头
要将某个项目添加到数组的开头,请使用数组扩展。
const arr = [1, 2, 3];
const result = [0, ...arr];
console.log(result);
// [0, 1, 2, 3]
不要使用unshift方法,因为它会改变原始数组。
2. 将元素添加到数组末尾
要将某个项目附加到数组末尾,请使用数组扩展。
const arr = [1, 2, 3];
const result = [...arr, 4];
console.log(result);
// [1, 2, 3, 4]
不要使用push方法,因为它会改变原始数组。
3. 从数组开头删除一个元素
要删除数组中的第一个项目,请使用slice方法。
const arr = [1, 2, 3];
// Keep index 1 and everything after that.
const result = arr.slice(1);
console.log(result);
// [2, 3]
不要使用shift或splice方法,它们会改变原始数组。
4. 从数组末尾删除一个元素
要删除数组中的最后一项,请使用slice方法。
const arr = [1, 2, 3];
// Keep index 0 and everything after that, except one element at the array.
const result = arr.slice(0, -1);
console.log(result);
// [1, 2]
不要使用pop或splice方法,它们会改变原始数组。
5. 在数组索引处插入元素
要在数组的特定索引处添加项目,请使用toSpliced方法。
const arr = [1, 2, 3];
// Keep index 1, delete 0 elements, add the element "one point five" and keep everything after that.
const result = arr.toSpliced(1, 0, "one point five");
console.log(result);
// [1, "one point five", 2, 3]
不要使用splice方法,因为它会改变原始数组。
6. 替换数组中索引处的元素
要替换数组中某个索引的项目,请使用toSpliced或with方法。
const arr = [1, 2, 3];
// Using toSpliced.
// Keep index 1, delete 1 elements, add the element "two" and keep everything after that.
const result1 = arr.toSpliced(1, 1, "two");
console.log(result1);
// [1, "two", 3]
// Using with.
// Copy the old array arr with index 1 replaced with "two".
const result2 = arr.with(1, "two");
console.log(result2);
// [1, "two", 3]
不要使用splice方法,因为它会改变原始数组。
7. 删除数组中索引处的元素
要从数组中删除某个项目,请使用toSpliced方法。
const arr = [1, 2, 3];
// At index 1, delete 1 elements.
const result = arr.toSpliced(1, 1);
console.log(result);
// [1, 3]
不要使用splice方法,因为它会改变原始数组。
8. 从数组中按值删除元素
要从数组中删除特定值,请使用过滤方法。
const arr = [1, 2, 3];
const result = arr.filter((element) => element !== 2);
console.log(result);
// [1, 3]
不要将indexOf与splice方法一起使用,因为这会改变原始数组。
9. 根据属性从数组中删除对象
要从数组中删除具有特定属性的对象,请使用过滤方法。
const arr = [{ num: 1 }, { num: 2 }, { num: 3 }];
const result = arr.filter((obj) => obj.num !== 2);
console.log(result);
// [{ num: 1 }, { num: 3 }]
不要将findIndex与splice方法一起使用,因为这会改变原始数组。
10. 检查数组是否包含元素
要检查数组是否包含值,请使用includes方法。
const arr = [1, 2, 3];
const result = arr.includes(2);
console.log(result);
// true
11. 检查数组是否包含具有属性的对象
要检查数组是否包含具有属性的对象,请使用某种方法。
const arr = [{ num: 1 }, { num: 2 }, { num: 3 }];
const result = arr.some((obj) => obj.num === 2);
console.log(result);
// true
12. 检查数组中的所有对象是否都具有某个属性
要检查数组中的每个对象是否都具有属性,请使用every方法。
const arr1 = [{ num: 1 }, { num: 2 }, { num: 3 }];
const result1 = arr1.every((obj) => obj.num === 2);
console.log(result1);
// false
const arr2 = [{ num: 2 }, { num: 2 }, { num: 2 }];
const result2 = arr2.every((obj) => obj.num === 2);
console.log(result2);
// true
13. 将数组转换为对象
要将数组转换为自定义对象,请使用reduce方法。
// A function which maps a key to a value.
const arr1 = [1, 2, 3];
const result1 = arr1.reduce((acc, cur, index) => {
acc[`attr${index}`] = cur;
return acc;
}, {});
console.log(result1);
// { attr0: 1, attr1: 2, attr2: 3 }
// A function which count occurrences could look like this.
const arr2 = ["a", "b", "c", "c"];
const result2 = arr2.reduce((acc, cur) => {
if (acc[cur]) {
acc[cur] += 1;
} else {
acc[cur] = 1;
}
return acc;
}, {});
console.log(result2);
// { a: 1, b: 1, c: 2 })
// A function which maps elements in array to boolean values can look like this.
// I.e. convert array to object keys.
const arr3 = ["a", "b", "c"];
const truthValues = ["b", "c"];
const result3 = arr3.reduce((acc, cur) => {
acc[cur] = truthValues.includes(cur);
return acc;
}, {});
console.log(result3);
// { a: false, b: true, c: true })
14. 将对象数组转换为对象
要将对象数组转换为对象,请使用Object.assign方法和数组扩展语法。
const arr = [{ attr1: 1 }, { attr2: 2 }, { attr3: 3 }];
const result = Object.assign({}, ...arr);
console.log(result);
// { attr1: 1, attr2: 2, attr3: 3 }
15. 将对象转换为数组
要从对象创建数组,请使用Object.keys、Object.values或Object.entries,可能还需要结合使用map方法。
const obj = { a: 1, b: 2, c: 3 };
// Array of keys.
const result1 = Object.keys(obj);
console.log(result1);
// ["a", "b", "c"]
// Array of values.
const result2 = Object.values(obj);
console.log(result2);
// [1, 2, 3]
// Array of key-value objects.
const result3 = Object.entries(obj).map(([key, value]) => ({ key, value }));
console.log(result3);
// [{ key: "a", value: 1 }, { key: "b", value: 2 }, { key: "c", value: 3 }]
在某些情况下,链接一些映射和过滤方法来修改和过滤值是很有用的。
const obj = { a: 1, b: 2, c: 3 };
// Array of squared values greater than 3.
const result1 = Object.values(obj)
.map((value) => value * value)
.filter((value) => value > 3);
console.log(result1);
// [4, 9]
// Array of key-value objects which has a value greater than 1.
const result2 = Object.entries(obj)
.map(([key, value]) => ({ key, value }))
.filter((keyValueObj) => keyValueObj.value > 1);
console.log(result2);
// [{ key: "b", value: 2 }, { key: "c", value: 3 }]
16. 合并两个数组
要合并两个 JavaScript 数组,请使用concat方法或数组的扩展语法。
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// Concat method is faster.
const combinedArray1 = arr1.concat(arr2);
console.log(combinedArray1);
// [1, 2, 3, 4, 5, 6]
// Spread syntax may be more readable.
const combinedArray2 = [...arr1, ...arr2];
console.log(combinedArray2);
// [1, 2, 3, 4, 5, 6]
不要使用push方法,因为它会改变原始数组。
17. 对数组进行排序
如果要按值对数组进行排序,请使用toStorted方法。
toStorted方法是稳定的,这意味着它保持相等元素的顺序不变。该方法不是原地方法,这通常是一件好事,因为这意味着它不会改变现有数组。
// To sort strings.
let arr1 = ["b", "c", "a"];
const result1 = arr1.toSorted();
console.log(result1);
// ["a", "b", "c"]
// Note: Numbers are sorted by their toString value,
// not by their numerical value!
const arr2 = [10, 1, 5];
const result2 = arr2.toSorted();
console.log(result2);
// [1, 10, 5]
// To sort numbers, use a comparator.
const arr3 = [10, 1, 5];
const result3 = arr3.toSorted((a, b) => a - b);
console.log(result3);
// [1, 5, 10]
不要使用sort方法,因为它进行就地排序,所以会改变原始数组。
18. 对对象数组进行排序
要按值对数组进行排序,请使用带有比较器的toStorted方法。比较器是一个函数,用于确定两个值中哪个应该先排序。
toStorted方法是稳定的,这意味着它保持相等元素的顺序不变。该方法不是原地方法,这通常是一件好事,因为这意味着它不会改变现有数组。
const arr = [{ num: 3 }, { num: 1 }, { num: 2 }];
// ObjA will be sorted before objB if comparator returns a positive value.
const byNumberAttribute = (objA, objB) => objA.num - objB.num;
const result1 = arr.toSorted(byNumberAttribute);
console.log(result1);
// [{ num: 1 }, { num: 2 }, { num: 3 }]
// More generic comparator.
const byAttribute = (attr) => (objA, objB) => objA[attr] - objB[attr];
const result2 = arr.toSorted(byAttribute("num"));
console.log(result2);
// [{ num: 1 }, { num: 2 }, { num: 3 }]
// Note. The comparator function must return an integer value.
// If you need to sort other data types, return 1, 0 or -1.
const arr3 = [{ letter: "c" }, { letter: "a" }, { letter: "b" }];
const alphabetically = (objA, objB) => {
if (objA.letter < objB.letter) {
return -1;
}
if (objA.letter > objB.letter) {
return 1;
}
// objA === objB
return 0;
};
const result3 = arr3.toSorted(alphabetically);
console.log(result3);
// [{ letter: 'a' }, { letter: 'b' }, { letter: 'c' }]
不要使用排序方法,因为它会改变原始数组。
19. 反转数组
要反转数组中的所有值,请使用toReversed方法。
const arr = [1, 2, 3];
const result = arr.toReversed(2);
console.log(result);
// [3, 2, 1]
20. 从数组中删除重复项
要删除数组中的重复元素,请使用过滤方法或集合。
const arr = [1, 2, 3, 2, 1];
// Using filter method.
const result1 = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(result1);
// [1, 2, 3]
// Using a set.
const result2 = [...new Set(arr)];
console.log(result2);
// [1, 2, 3]