HOWTO · JavaScript
JavaScript 中数组的子集
在今天的文章中,我们将学习如何在 JavaScript 中提取数组的子集。
本页内容
需要在新数组中取得选定范围,同时保持原数组不变时,请使用 slice()。需要从原数组中删除、替换或插入元素时,请使用 splice()。这两种方法都会返回数组,但只有 splice() 会修改调用它的数组。
使用 slice() 提取子集而不修改数组
slice(start, end) 会返回所选范围的浅拷贝。start 索引所指的元素会包含在结果中;可选的 end 索引则不包含在内。省略 end 时,会选取从 start 到最后一个元素的内容。由于结果是浅拷贝,嵌套对象仍通过引用共享;不过,在结果中添加或删除元素不会改变原数组。
索引从零开始计数。负索引表示从末尾往回数:-1 是最后一个元素,-2 是倒数第二个元素。如果起始索引大于或等于数组长度,结果为空;如果结束索引超出数组长度,则按数组长度处理。如果规范化后的结束索引小于或等于起始索引,结果也为空。这些规则让你无需先计算每个索引,就能方便地选取开头部分、中间范围或末尾部分。
例如,范围从索引 1 开始,到索引 4 结束时,选中的位置是 1、2 和 3。把两个参数分别理解为「第一个包含的位置」和「第一个不包含的位置」,有助于将范围用于用户界面或计算。返回的数组是一个独立容器,因此之后增删其中的元素,不会改变原数组的元素顺序。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
const scores = [12, 18, 25, 31, 44];
const middleScores = scores.slice(1, 4);
console.log(JSON.stringify(middleScores));
console.log(JSON.stringify(scores));
[18,25,31]
[12,18,25,31,44]
示例会先输出选定的范围,再输出未改变的原数组。要取得末尾部分,可以使用负起始索引,例如 scores.slice(-2);要复制整个数组,可以使用 scores.slice()。
如需了解此方法的完整行为,请参阅 MDN 的 slice() 参考文档。
使用 splice() 提取并修改数组元素
splice(start, deleteCount, ...items) 会直接修改原数组。它从 start 指定的位置开始,最多删除 deleteCount 个元素,然后在该位置插入给定的元素。此方法会按原有顺序返回一个包含已删除元素的新数组。如果需要同时查看修改后的原数组和返回值,请保留对原数组的引用。
start 索引从零开始。负起始索引表示从数组末尾往回数;如果起始索引超出数组长度,则按数组末尾处理,此时可以追加元素。省略 deleteCount 时,会删除从 start 到末尾的元素。传入 0 表示不删除任何元素,因此给定的元素会直接插入,而原有元素仍保留。负的 deleteCount 也不会删除元素。如果 deleteCount 大于剩余元素数,删除操作会在数组末尾停止。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
const fruits = ['Kiwi', 'Orange', 'Apple', 'Banana'];
const removedFruits = fruits.splice(0, 2, 'Mango');
console.log(JSON.stringify(removedFruits));
console.log(JSON.stringify(fruits));
["Kiwi","Orange"]
["Mango","Apple","Banana"]
示例会先输出被删除的值,再输出已修改的 fruits 数组;Mango 会替换被删除的范围。
如果要删除索引 1 及其之后的所有元素,请使用 fruits.splice(1)。如果要在索引 1 处插入元素而不删除任何元素,请使用 fruits.splice(1, 0, 'Pear')。如需了解方法详情,请参阅 MDN 的 splice() 参考文档。
如何选择 slice() 或 splice()
如果你需要读取或传递数组的一部分,同时保留原数组的顺序,请选择 slice()。它的结束索引不包含在结果中,返回值是选定范围的浅拷贝。如果需要编辑现有数组,请选择 splice();它会返回被删除的部分,如果没有删除任何元素,返回值可能为空。
例如,使用 const page = items.slice(offset, offset + pageSize) 可以取得一页数据,同时保持 items 不变。如果确实要从 items 中移除这些元素,可以使用 const removed = items.splice(index, count)。如果后续代码依赖原数组,请优先使用 slice(),或在调用 splice() 前有意创建副本。
原文还提供了完整的 JSFiddle 示例,可供你交互式尝试这两种方法。