📚 核心方法对比总览
| 方法 | 功能 | 修改原数组 | 返回值 | 时间复杂度 | 记忆技巧 |
|---|
slice() | 切片/提取 | ❌ 否 | 新数组/字符串 | O(n) | "切一片蛋糕" - 原蛋糕还在 |
splice() | 剪接/增删改 | ✅ 是 | 被删除元素数组 | O(n) | "剪辑电影" - 原片被修改 |
shift() | 移除第一个 | ✅ 是 | 移除的元素 | O(n) | "移除队首" |
unshift() | 前面添加 | ✅ 是 | 新长度 | O(n) | "反方向shift" |
pop() | 移除最后一个 | ✅ 是 | 移除的元素 | O(1) | "弹出栈顶" |
push() | 后面添加 | ✅ 是 | 新长度 | O(1) | "推入栈" |
一、🔪 slice() - 切片方法
1.1 基本语法
array.slice(startIndex, endIndex)
string.slice(startIndex, endIndex)
1.2 参数详解
const arr = ['A', 'B', 'C', 'D', 'E'];
arr.slice(1, 3);
arr.slice(0, -1);
arr.slice(2);
arr.slice(-2);
const copy = arr.slice();
1.3 实际应用
const original = [1, 2, { name: 'John' }];
const copy = original.slice();
copy[0] = 999;
copy[2].name = 'Jane';
function paginate(items, page = 1, pageSize = 10) {
const start = (page - 1) * pageSize;
return items.slice(start, start + pageSize);
}
const url = 'https://api.example.com/users';
const domain = url.slice(8, url.indexOf('/', 8));
const getFirstN = (arr, n) => arr.slice(0, n);
const getLastN = (arr, n) => arr.slice(-n);
二、✂️ splice() - 剪接方法
2.1 基本语法
array.splice(startIndex, deleteCount, item1, item2, ...)
2.2 三种主要用途
const fruits = ['🍎', '🍌', '🍊', '🍇'];
const removed = fruits.splice(1, 2);
fruits.splice(1, 0, '🍉', '🍓');
fruits.splice(2, 1, '🍍');
2.3 实用技巧
arr.splice(-1, 1);
arr.splice(0, 1);
arr.splice(0, arr.length);
const insertAt = (arr, index, ...items) => {
arr.splice(index, 0, ...items);
return arr;
};
三、🔄 shift() / unshift() - 队列前端操作
3.1 shift() - 移除第一个
const queue = ['任务1', '任务2', '任务3'];
const currentTask = queue.shift();
while (queue.length > 0) {
const task = queue.shift();
processTask(task);
}
3.2 unshift() - 前面添加
const history = ['页面2', '页面3'];
history.unshift('页面1');
function addLogPrefix(logs, prefix) {
logs.unshift(`[${prefix}]:`);
return logs;
}
3.3 性能注意
const bigArray = new Array(1000000).fill('item');
class Deque {
constructor() {
this.items = [];
}
addFront(item) {
this.items.unshift(item);
}
removeFront() {
return this.items.shift();
}
}
四、📌 pop() / push() - 栈/队列后端操作
4.1 push() - 后面添加
const stack = [];
stack.push('操作1');
stack.push('操作2');
stack.push('操作3');
const path = [];
path.push('users');
path.push('documents');
path.push('file.txt');
4.2 pop() - 移除最后一个
const lastOperation = stack.pop();
const undoStack = [];
const redoStack = [];
function doAction(action) {
undoStack.push(action);
execute(action);
}
function undo() {
if (undoStack.length > 0) {
const action = undoStack.pop();
redoStack.push(action);
revert(action);
}
}
五、🎯 对比总结
5.1 读写特性对比
const arr = [1, 2, 3, 4, 5];
const sliceResult = arr.slice(1, 4);
console.log(arr);
const spliceResult = arr.splice(1, 3);
console.log(arr);
5.2 操作位置对比
操作位置 前面 中间 后面
-------------------------------------------------
取出/删除 shift() splice() pop()
添加/插入 unshift() splice() push()
只读切片 slice() slice() slice()
5.3 返回值对比
const arr = ['a', 'b', 'c', 'd'];
arr.slice(1, 3);
arr.splice(1, 2);
arr.shift();
arr.unshift('x');
六、🚀 最佳实践
6.1 选择指南
| 场景 | 推荐方法 | 原因 |
|---|
| 需要原数组不变 | slice() | 创建副本,不影响原始数据 |
| 需要修改原数组 | splice() | 原地操作,节省内存 |
| 队列操作(先进先出) | push() + shift() | 符合队列语义 |
| 栈操作(后进先出) | push() + pop() | 符合栈语义 |
| 数组前端操作频繁 | 考虑双向链表 | shift/unshift性能差 |
6.2 性能优化
const largeArray = new Array(100000).fill('item');
class OptimizedArray {
constructor() {
this.items = [];
this.frontIndex = 0;
}
shift() {
if (this.frontIndex >= this.items.length) return undefined;
const item = this.items[this.frontIndex];
this.frontIndex++;
if (this.frontIndex > 1000) {
this.items = this.items.slice(this.frontIndex);
this.frontIndex = 0;
}
return item;
}
}
6.3 现代JavaScript替代
const arr = [1, 2, 3, 4, 5];
const copy1 = arr.slice();
const copy2 = [...arr];
const copy3 = Array.from(arr);
arr.push(6, 7);
const newArr = [...arr, 6, 7];
arr.unshift(0);
const newArr2 = [0, ...arr];
七、📝 记忆口诀
7.1 按功能记忆
读操作:slice (只读不写)
写操作:splice (增删改查)
队列头:shift/unshift
队列尾:pop/push
7.2 按名字记忆
slice → "切" → 切一片 → 只读
splice → "plice"(连接)→ 修改连接
shift → 移动 → 移除第一个
unshift → 反移动 → 前面添加
pop → "砰" → 弹出最后一个
push → 推 → 后面推入
7.3 一句话总结
slice切,splice改,shift/unshift动头,pop/push动尾
八、🔧 实用代码片段
const ArrayUtils = {
safeSlice: (arr, start = 0, end = arr.length) => {
const len = arr.length;
start = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
end = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);
return arr.slice(start, end);
},
removeItems: (arr, indices) => {
indices.sort((a, b) => b - a);
indices.forEach(index => {
arr.splice(index, 1);
});
return arr;
},
insertSorted: (arr, item, compareFn = (a, b) => a - b) => {
let low = 0, high = arr.length;
while (low < high) {
const mid = Math.floor((low + high) / 2);
if (compareFn(arr[mid], item) < 0) {
low = mid + 1;
} else {
high = mid;
}
}
arr.splice(low, 0, item);
return arr;
}
};
九、📊 时间复杂度总结
| 操作 | 时间复杂度 | 说明 |
|---|
slice(start, end) | O(k) | k = end - start |
splice(start, deleteCount, ...items) | O(n) | 需要移动元素 |
shift() | O(n) | 需要移动所有元素 |
unshift(...items) | O(n + m) | n=原长度, m=新增个数 |
pop() | O(1) | 直接移除最后一个 |
push(...items) | O(m) | m=新增个数 |
十、✅ 快速参考卡
const part = arr.slice(start, end);
const removed = arr.splice(start, deleteCount, ...items);
queue.push(item);
const item = queue.shift();
stack.push(item);
const item = stack.pop();
arr.unshift(...items);
arr.shift();
arr.push(...items);
arr.pop();
最后提醒:
- ✅ 需要保留原数组时用
slice()
- ✅ 需要修改原数组时用
splice()
- ✅ 队列操作用
push() + shift()
- ✅ 栈操作用
push() + pop()
- ❌ 避免在大数组上频繁使用
shift()/unshift()