You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何两段toggleComplete函数代码执行结果不同?一段丢失数组元素

两段toggleComplete代码执行结果差异的原因解析

问题描述

为何以下第一段toggleComplete函数代码执行后,todos数组仅保留completed相关元素、其余元素被删除?而第二段代码执行后,数组所有元素保留,仅修改目标元素的completed属性(符合预期行为)。

第一段代码

const toggleComplete = (id) => {
  const updatedTodos = todos.map((todo) =>
    todo.id === id ? todo.completed = !todo.completed : todo
  );
  setTodos(updatedTodos);
}

第二段代码

const toggleComplete = (id) => {
  const updatedTodos = todos.map((todo) => {
    if (todo.id === id) {
      todo.completed = !todo.completed;
    }
    return todo;
  });
  setTodos(updatedTodos);
}

差异原因解析

核心差异在于map回调函数的返回值逻辑不同:

  • 第一段代码使用三元表达式时,匹配id的分支执行的是todo.completed = !todo.completed——这是一个赋值操作,赋值语句的返回值是被赋的布尔值(true/false),而非修改后的整个todo对象。因此map遍历后,updatedTodos数组中,匹配id的位置会被替换成布尔值,不匹配的位置保留原todo对象。后续渲染或处理时,布尔值没有todo对象的属性(如id、text等),会被过滤或忽略,看起来就像“其余元素被删除”。
  • 第二段代码的if语句仅修改todo对象的completed属性,无论是否匹配id,最终都会返回整个todo对象。因此map生成的updatedTodos数组全是完整的todo对象,所有元素都被保留,仅目标元素的completed属性被修改,符合预期。

补充:符合React不可变原则的写法

两段代码都直接修改了原todo对象(对象是引用类型),虽然能实现功能,但违反了React的不可变数据原则,可能导致意外的渲染问题。推荐创建新对象来修改属性:

const toggleComplete = (id) => {
  const updatedTodos = todos.map((todo) => 
    todo.id === id ? {...todo, completed: !todo.completed} : todo
  );
  setTodos(updatedTodos);
};

内容的提问来源于stack exchange,提问作者metrallador10

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:15:12