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

原生JavaScript Todo项目:如何实现对象数组的可变与不可变更新?

原生JS Todo项目:对象数组的可变/不可变动态更新方法

我正在用原生JavaScript开发Todo项目,需要编写updateProject函数来更新项目的标题、描述、优先级等信息,想了解如何对对象数组进行可变或不可变的动态更新。现有代码如下:

// 示例:直接修改任务标题
project1.tasks[2].title = newTitle
// Project Manager 对象
const PM = {
    // 空项目数组
    projects: [],
    // 添加项目到数组的方法
    addProject(project) {
        this.projects.push(project)
    },
    deleteProject(project) {
        const projectIndex = this.projects.indexOf(project)
        if (projectIndex !== -1) {
            this.projects.splice(projectIndex, 1)
            return true
        }
        return false
    },
    updateProject() {
        // 待实现:更新项目标题、描述、优先级
    }
}
const projectFactory = (title) => ({
    title,
    tasks: [],
    addTask(task) {
        this.tasks.push(task)
    },
    deleteTask(task) {
        const taskIndex = this.tasks.indexOf(task)
        if (taskIndex !== -1) {
            this.tasks.splice(taskIndex, 1)
            return true
        }
        return false
    }
})
const createProject = (title) => {
    const project = projectFactory(title)
    return project
}
const taskFactory = (title, description, dueDate, priority) => ({ title, description, dueDate, priority })

const createTask = (title, description, dueDate, priority) => {
    const task = taskFactory(title, description, dueDate, priority)
    return task
}
const project1 = projectFactory("Clean")
const task1 = taskFactory("Clean kitchen", "Wash dishes", "1/19/2023", "Medium")

PM.addProject(project1)
project1.addTask(task1)

我参考过StackOverflow的类似问题,但它们要么用ID,要么基于React实现,不符合我的需求。


一、可变更新方案(直接修改原对象)

这种方式直接修改原项目/任务对象,无需创建新实例,适合不需要追踪数据变更历史的场景。

1. 实现PM的updateProject方法

传入目标项目和要更新的属性,直接覆盖原对象的对应值:

updateProject(targetProject, updates) {
    const projectIndex = this.projects.indexOf(targetProject)
    if (projectIndex === -1) return false
    // 遍历更新属性,直接修改原对象
    Object.assign(this.projects[projectIndex], updates)
    return true
}

使用示例:

// 更新project1的标题并添加优先级属性
PM.updateProject(project1, { title: "Deep Clean", priority: "High" })

2. 动态更新任务

和示例逻辑一致,直接通过数组索引修改任务属性,支持批量更新:

// 修改project1中第3个任务的标题
project1.tasks[2].title = "Mop kitchen floor"
// 批量更新任务的描述和优先级
Object.assign(project1.tasks[2], {
    description: "Mop all areas and clean baseboards",
    priority: "High"
})

二、不可变更新方案(返回新数据,不修改原对象)

这种方式会创建新的数组或对象副本,原数据保持不变,适合需要追踪数据变化、实现撤销/重做功能的场景。

1. 实现不可变的updateProject方法

updateProject(targetProject, updates) {
    const projectIndex = this.projects.indexOf(targetProject)
    if (projectIndex === -1) return this.projects // 返回原数组
    
    // 创建新数组,替换目标项目为更新后的副本
    return [
        ...this.projects.slice(0, projectIndex),
        { ...targetProject, ...updates },
        ...this.projects.slice(projectIndex + 1)
    ]
}

使用示例:

// 更新后得到新的projects数组,原PM.projects不受影响
const updatedProjects = PM.updateProject(project1, { title: "Deep Clean", priority: "High" })
// 如需替换原数组,手动赋值
PM.projects = updatedProjects

2. 不可变更新任务

// 创建新的项目对象,修改指定任务的属性,原project1保持不变
const updatedProject = {
    ...project1,
    tasks: [
        ...project1.tasks.slice(0, 2),
        { ...project1.tasks[2], title: "Mop kitchen floor" },
        ...project1.tasks.slice(3)
    ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:01:30