Array.prototype.copyWithin()
Array.prototype.copyWithin()
方法用于将数组中的指定部分复制到同一数组中的另一个位置,并返回修改后的数组。该方法会直接修改原数组。
参数
copyWithin()
接受三个参数:target
、start
和 end
,返回修改后的数组。
const arr = [1, 2, 3, 4, 5];
const newArr = arr.copyWithin(0, 3, 4);
// Array.prototype.copyWithin
console.log(newArr); // [4, 2, 3, 4, 5]
target
指定复制到的目标起始位置的数组索引。
start
指定开始复制的起始位置的数组索引。
end
指定停止复制的结束位置的数组索引(不包括该位置的元素)。如果超过数组长度,则复制到数组末尾。
使用示例
copyWithin()
方法在以下几种情况下具有不同的行为:
3~4
表示复制下标为 3 到 4 之间的元素,不包括下标 4。
当 end
超过数组长度时,复制将持续到数组的末尾。
如果 target
超过数组长度,则不会进行任何替换。
当 target
大于 start
时,正常进行替换。
如果 start
或 end
是负数,则通过 start + length
和 end + length
计算实际位置。
仅当 target
覆盖整个数组元素时,从 target
位开始替换,剩余部分不受影响,且数组长度保持不变。
copyWithin
会修改原数组。
const arr = [1, 2, 3, 4, 5];
const newArr = arr.copyWithin(0, 3, 4);
console.log(newArr); // [4, 2, 3, 4, 5]
元素为引用值
copyWithin()
进行的是浅拷贝,复制的对象仍然引用同一个内存地址。
const arr = [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' },
{ id: 4, name: '赵六' },
{ id: 5, name: '六七' },
{ id: 6, name: '周八' },
];
const targetBefore = arr[2];
const newArr = arr.copyWithin(0, 2, 3);
const targetAfter = arr[0];
console.log(targetBefore === targetAfter); // true
console.log(newArr);
// [
// { id: 3, name: '王五' },
// { id: 2, name: '李四' },
// { id: 3, name: '王五' },
// { id: 4, name: '赵六' },
// { id: 5, name: '六七' },
// { id: 6, name: '周八' },
// ]
类数组对象
copyWithin()
可以应用于类数组对象,通过修改 this
指向。
const obj = {
0: 1,
1: 2,
2: 3,
3: 4,
4: 5,
length: 5,
};
const newObj = [].copyWithin.call(obj, 0, 2, 4);
console.log(newObj); // { '0': 3, '1': 4, '2': 3, '3': 4, '4': 5, length: 5 }
console.log(obj === newObj); // true
位运算
在 copyWithin
的实现中,位运算用于处理参数的转换,确保参数为有效的整数。
有符号位移
左位移 (<<
)
将数字的二进制位向左移动指定的位数,左侧溢出的位将被丢弃,右侧用零填充。
console.log(5 << 2); // 20
右位移 (>>
)
将数字的二进制位向右移动指定的位数,保留符号位。
console.log(5 >> 2); // 1
无符号位移
无符号位移(逻辑位移)不考虑符号位,高位补 0
,结果总为正数。
右位移 (>>>
)
将数字的二进制位向右移动指定的位数,左侧用零填充。
const a = [98, 85, 65, 92, 78, 98, 78, 65, 87, 85, 87, 48, 75, 48, 65, 48];
console.log(a.length >>> 0); // 16
自定义实现 copyWithin
以下是 Array.prototype.copyWithin
的自定义实现 myCopyWithin
:
Array.prototype.myCopyWithin = function (target, start, end) {
if (this == null) {
throw new TypeError('this is null or not defined');
}
const obj = Object(this);
const len = obj.length >>> 0;
let to = target >> 0;
to = to < 0 ? Math.max(len + to, 0) : Math.min(to, len);
let from = start >> 0;
from = from < 0 ? Math.max(len + from, 0) : Math.min(from, len);
let final = end !== undefined ? end >> 0 : len;
final = final < 0 ? Math.max(len + final, 0) : Math.min(final, len);
const count = Math.min(final - from, len - to);
let direction = 1;
if (from < to && to < from + count) {
direction = -1;
from += count - 1;
to += count - 1;
}
for (let i = 0; i < count; i++) {
if (from in obj) {
obj[to] = obj[from];
} else {
delete obj[to];
}
from += direction;
to += direction;
}
return obj;
};
const arr = [1, 2, 3, 4, 5];
const newArr = arr.myCopyWithin(0, 3, 4);
console.log(newArr); // [4, 2, 3, 4, 5]
注意事项
copyWithin()
会修改原数组。- 方法不会改变数组的长度。
- 复制的元素是浅拷贝,对于引用类型的元素,复制的是引用地址。
链接
了解更多信息,请访问 Array.prototype.copyWithin() - JavaScript | MDN。