可变vs不可变
在JavaScript中,可变操作指直接修改原始数据结构。例如:
js
复制代码
const arr = [1, 2, 3];
arr.push(4); // 可变操作
console.log(arr); // 输出: [1, 2, 3, 4]
不可变方法返回新的数据结构
js
复制代码
const arr = [1, 2, 3];
const newArr = [...arr, 4]; // 不可变操作
console.log(arr); // 输出: [1, 2, 3]
console.log(newArr); // 输出: [1, 2, 3, 4]
虽然可能带来一些性能开销,但能够提高代码的可预测性和可维护性。
slice vs splice
假设我们正在开发一个待办事项列表应用,需要实现移除已完成任务的功能:
js
复制代码
// 使用splice (可变方法)
function removeCompletedTasks(tasks) {
for (let i = tasks.length - 1; i >= 0; i--) {
if (tasks[i].completed) {
tasks.splice(i, 1);
}
}
return tasks;
}
// 使用slice (不可变方法)
function removeCompletedTasksImmutable(tasks) {
return tasks.filter(task => !task.completed);
}
const tasks = [
{ id: 1, text: "周一", completed: false },
{ id: 2, text: "周二", completed: true },
{ id: 3, text: "周三", completed: false }
];
console.log(removeCompletedTasks([...tasks]));
console.log(removeCompletedTasksImmutable(tasks));
在这个例子中,splice方法直接修改原数组,而filter方法(基于slice的思想)创建一个新数组。不可变方法通常更受欢迎,因为它们有助于优化渲染性能。
现代方法:at(), with(), 和 toSorted()
1. at(): 安全访问数组元素
js
复制代码
const fruits = ['苹果', '香蕉', '橙子'];
console.log(fruits.at(-1)); // 输出: '橙子'
2. with(): 不可变地更新数组元素
js
复制代码
const updatedFruits = fruits.with(1, '葡萄');
console.log(fruits); // 输出: ['苹果', '香蕉', '橙子']
console.log(updatedFruits); // 输出: ['苹果', '葡萄', '橙子']
3. toSorted(): 不可变排序
js
复制代码
const numbers = [3, 1, 4, 1, 5, 9];
const sortedNumbers = numbers.toSorted();
console.log(numbers); // 输出: [3, 1, 4, 1, 5, 9]
console.log(sortedNumbers); // 输出: [1, 1, 3, 4, 5, 9]