在处理业务时,善用Array中的方法,如splice
,可以极大地减少我们的工作量并避免冗余的循环代码。通过splice
,我们可以方便地对目标数组进行增、删、改操作。
那么有一点我很好奇,就是它本身工作原理是怎么样的呢?
先看看语法:
array.splice(start[, deleteCount[, item1, item2, ...]])
下面我们来拆解它的参数以及返回值:
参数
start
:指定修改的开始位置(索引)。deleteCount
:一个整数,表示要移除的数组元素的个数。item1, item2, ...
:要添加进数组的元素,(可选)。如果不指定,则splice
仅仅删除数组元素。
返回值
由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。
知道其本身的参数以及返回值,再来看看它基本做了什么
-
检查参数有效性:
start
必须是一个整数,如果它是负数,则从数组末尾开始计算位置。deleteCount
必须是一个非负整数,如果省略或为大于array.length - start
(即超出范围),则删除从start
到数组末尾的所有元素。
-
计算实际开始索引:
- 如果
start
是负数,则start
=array.length + start
。 - 如果
start
大于或等于数组长度,则不执行任何操作,返回一个空数组。
- 如果
-
删除指定数量的元素:
- 从
start
索引开始,删除deleteCount
个元素。 - 如果
deleteCount
大于或等于从start
到数组末尾的元素个数,则删除从start
到数组末尾的所有元素。
- 从
-
插入新元素:
- 从
start
索引开始,插入指定的新元素。
- 从
-
返回被删除的元素:
- 返回一个包含被删除元素的新数组。如果没有删除任何元素,则返回一个空数组。
源码实现
那么接下来我们围绕上面逻辑实现自己的splice
定义一个函数:function customSplice(array, start, deleteCount, ...itemsToAdd) { }
1、处理负数索引
if (start < 0) {
start = Math.max(0, array.length + start);
}
2、限制删除的元素数量不超过从start
到数组末尾的元素数量
const maxDeleteCount = array.length - start;
deleteCount = (deleteCount > maxDeleteCount) ? maxDeleteCount : deleteCount;
3、创建一个新数组来存储被删除的元素
const deletedElements = [];
for (let i = 0; i < deleteCount; i++) {
deletedElements.push(array[start + i]);
}
4、创建一个新数组来存储修改后的数组内容,并且处理复制开始位置之前的元素
、复制要添加的新元素
、复制开始位置之后且未被删除的元素
。
const newArray = [];
//
for (let i = 0; i < start; i++) {
newArray.push(array[i]);
}
// 复制要添加的新元素
for (let item of itemsToAdd) {
newArray.push(item);
}
// 复制开始位置之后且未被删除的元素
for (let i = start + deleteCount; i < array.length; i++) {
newArray.push(array[i]);
}
5、更新原数组,并返回被删除数组
for (let i = 0; i < newArray.length; i++) {
array[i] = newArray[i];
}
array.length = newArray.length; // 确保原数组的长度正确
// 返回被删除的元素
return deletedElements;
把这些代码片段组合到我们的customSplice
函数中,就实现了array.splice
啦
function customSplice(array, start, deleteCount, ...itemsToAdd) {
// 处理负数索引
if (start < 0) {
start = Math.max(0, array.length + start);
}
// 限制删除的元素数量不超过从start到数组末尾的元素数量
const maxDeleteCount = array.length - start;
deleteCount = (deleteCount > maxDeleteCount) ? maxDeleteCount : deleteCount;
// 创建一个新数组来存储被删除的元素
const deletedElements = [];
for (let i = 0; i < deleteCount; i++) {
deletedElements.push(array[start + i]);
}
// 创建一个新数组来存储修改后的数组内容
const newArray = [];
// 复制开始位置之前的元素
for (let i = 0; i < start; i++) {
newArray.push(array[i]);
}
// 复制要添加的新元素
for (let item of itemsToAdd) {
newArray.push(item);
}
// 复制开始位置之后且未被删除的元素
for (let i = start + deleteCount; i < array.length; i++) {
newArray.push(array[i]);
}
// 更新原数组
for (let i = 0; i < newArray.length; i++) {
array[i] = newArray[i];
}
array.length = newArray.length; // 确保原数组的长度正确
// 返回被删除的元素
return deletedElements;
}
使用示例
let myArray = [1, 2, 3, 4, 5];
console.log(customSplice(myArray, 2, 2, 'a', 'b')); // 输出: [3, 4],myArray 变为 [1, 2, 'a', 'b', 5]
console.log(myArray)
函数逻辑简介:
- 处理了负数索引,将其转换为正数索引。
- 计算了要删除的元素数量,并确保它不会超过从
start
位置到数组末尾的元素数量。 - 创建了一个新数组
deletedElements
来存储被删除的元素。 - 创建了一个新数组
newArray
来存储修改后的数组内容。 - 通过循环将开始位置之前的元素、要添加的新元素以及开始位置之后且未被删除的元素复制到
newArray
中。 - 使用循环将
newArray
中的元素复制回原数组array
中,并更新原数组的长度。 - 返回了被删除的元素数组
deletedElements
。