在 JavaScript 中,Array类有许多强大的内置方法可以用来转换数组。有了这些方法,把一个数组转换成另一个数组会容易得多,比用简单的 for 循环或其他更直接的操作省事不少。
有些方法是纯函数,也就是说它们不会修改原数组,而是返回一个新数组。另一些方法则会改变调用它们的那个数组,并且不会返回修改后的数组。
下面介绍一些最常用的数组转换方法。完整的方法列表可以在 MDN 文档 中找到。
根据作为实参传入的函数对每个元素进行转换,从而创建一个新数组。这些回调函数通常写成箭头函数。
let arr = [1, 2, 3, 4];
const newArr = arr.map((value) => value - 1);
console.log(newArr);
// => [0, 1, 2, 3]
console.log(arr);
// => [1, 2, 3, 4]
值得注意的是,结果数组的长度始终与原数组相同。
给定一个过滤函数(对应当保留的元素返回 true,对应当移除的元素返回 false),过滤当前数组并创建一个新数组。
let arr = [1, 2, 3, 4];
arr.filter((value) => value % 2 === 0);
// => [2, 4]
用一个函数把数组归约为单个值,该函数接收一个_累加器_和数组的当前元素作为形参。这个函数说明了如何把当前元素合并进累加器,并返回将在下一次迭代中使用的累加器。
let arr = [1, 2, 3, 4];
// Get the sum of elements
arr.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
// => 10
// Classify the numbers by whether they are odd or not
arr.reduce(
(accumulator, currentValue) => {
if (currentValue % 2 === 0) {
accumulator.even.push(currentValue);
} else {
accumulator.odd.push(currentValue);
}
return accumulator;
},
{ even: [], odd: [] },
);
// => { even: [2, 4], odd: [1, 3] }
反转数组中的元素。
const arr = [1, 2, 3, 4];
arr.reverse();
// => [4, 3, 2, 1]
这个方法会修改调用它的数组。
给定起始下标和结束下标,从调用它的数组中创建一个子数组。
结束下标处的元素不会被包含在内。
此外,所有参数都是可选的:
起始下标默认为 0,结束下标默认为数组长度。
const arr = [1, 2, 3, 4];
arr.slice(1, 2); // [2]
arr.slice(1); // [2, 3, 4]
// You can also use negative numbers, that represent the indexes
// starting from the end of the array
arr.slice(-2); // [3, 4]
删除或替换数组中的元素,并/或添加新元素。 它接收以下参数:
splice 返回被删除的元素。
const arr = ['1', '2', '5', '6'];
// Insert an element at index 2
arr.splice(2, 0, '3');
console.log(arr);
// => ['1', '2', '3', '5', '6']
// Remove 2 elements, starting at index 3 and insert 2 elements
const removed = arr.splice(3, 2, '4', '5');
console.log(removed);
// => ['5', '6']
console.log(arr);
// => ['1', '2', '3', '4', '5']
// Remove 1 element at index 1
arr.splice(1, 1);
console.log(arr);
// => ['1', '3', '4', '5']
默认情况下,sort 会先把数组元素转换成字符串,然后进行字符串比较,以此对元素排序(参见比较概念)。
排序是_原地_进行的,也就是说原数组会被修改。
sort 还会返回这个修改后的数组,如果你想在它后面链式调用其他方法,这很方便。
const arr = ['c', 'a', 'z', 'b'];
const result = arr.sort();
console.log(result);
// => ['a', 'b', 'c', 'z']
console.log(arr);
// => ['a', 'b', 'c', 'z']
这种默认行为在你尝试对数字排序时会导致错误的结果。
const arr = [3, 1, 2, 10];
arr.sort();
// => [1, 10, 2, 3]
// Because the string '10' comes before '2' in dictionary order.
要自定义排序行为,可以把一个比较函数作为实参传入。 比较函数本身会以数组中的两个元素作为实参来调用。 它需要返回以下内容:
0
这样一来,只要传入正确的比较函数,数字排序的问题就能解决。
下面是一个用自定义比较函数对对象数组排序的例子。
const arr = [3, 1, 2, 10];
arr.sort((a, b) => a - b);
// => [1, 2, 3, 10]
// "a - b" is negative when b is greater than a, positive when
// a is greater than b and 0 when they are equal.
下面是一个用自定义比较函数对对象数组排序的例子。
const arr = [
{ name: 'Lydia', age: 7 },
{ name: 'Anne', age: 34 },
{ name: 'Holger', age: 59 },
];
arr.sort((item1, item2) => {
if (item1.name < item2.name) {
return -1;
}
if (item1.name > item2.name) {
return 1;
}
return 0;
});
// => [ { name: 'Anne', age: 34 }, { name: 'Holger', age: 59 },
// { name: 'Lydia', age: 7 } ]
自 2019 年起,语言规范规定排序必须是稳定的,但对性能(时间与空间复杂度)不作任何保证。