copyWithin()是数组原地复制方法,语法为arr.copyWithin(target, start, end),支持负索引与自动规范化,可高效实现左移、右移及循环移位,配合fill()或length截断完成真正位移。

copyWithin() 是数组的原地方法,它不创建新数组,只在原数组内部复制并覆盖元素,因此能高效实现数据位移(如左移、右移、循环移位),且完全避免内存分配。
理解 copyWithin 的参数逻辑
语法:arr.copyWithin(target, start, end)
- target:复制到的起始索引(含),可为负数(从末尾计)
- start:复制源的起始索引(含),默认 0
- end:复制源的结束索引(不含),默认 arr.length
- 所有索引会自动规范化(超出范围则截断,负数转正)
- 关键特性:即使 target 和源区间重叠,也能正确处理(类似 memmove)
实现向左位移 k 位(非循环)
将前 k 个元素“挤掉”,其余元素整体左移 k 位,末尾补 undefined 或由你清空:
const arr = [1, 2, 3, 4, 5]; const k = 2; arr.copyWithin(0, k); // [3, 4, 5, 4, 5] // 此时后 k 位是冗余副本,需手动清空 arr.fill(undefined, arr.length - k); // → [3, 4, 5, undefined, undefined]
注意:copyWithin 不自动擦除尾部,需配合 fill() 或 length 截断(如 arr.length -= k)来真正“丢弃”前 k 项。
实现向右位移 k 位(非循环)
先腾出右侧空间,再把原数据右推:
- 从后往前复制:用
copyWithin(arr.length - k, 0, arr.length - k) - 前 k 位变成冗余,用
fill(undefined, 0, k)清空
const arr = [1, 2, 3, 4, 5]; const k = 2; arr.copyWithin(arr.length - k, 0, arr.length - k); // [1, 2, 1, 2, 3] arr.fill(undefined, 0, k); // → [undefined, undefined, 1, 2, 3]
实现循环左移 k 位(原地无额外内存)
利用三次翻转技巧(经典算法),全程只用 copyWithin + reverse 模拟(但 reverse 会修改原数组);更直接的方式是分段 copyWithin:
- 设 n = arr.length,k = k % n;若 k === 0 直接返回
- 步骤一:反转前 k 项 →
copyWithin(0, n−k, n)把后 k 项挪到开头 - 步骤二:反转后 n−k 项 →
copyWithin(k, 0, n−k)把原前 n−k 项挪到后面 - 但注意:一次 copyWithin 无法完成“交换两段”,需辅助逻辑
更稳妥的循环左移(推荐):
function rotateLeft(arr, k) {
const n = arr.length;
if (n === 0 || k % n === 0) return;
const shift = ((k % n) + n) % n;
// 先把后 shift 个元素复制到开头
arr.copyWithin(0, n - shift, n);
// 再把原前 n-shift 个元素复制到 shift 开始的位置
arr.copyWithin(shift, 0, n - shift);
// 此时前 shift 个是原后 shift 个,后 n-shift 个是原前 n-shift 个 → 完成循环左移
}
// 示例:[1,2,3,4,5], k=2 → [3,4,5,1,2]
整个过程未 new 数组、未 push/pop、未 slice,纯靠索引移动与覆盖,真正零内存分配。










