遍历JSON数组生成结构化对象时,时间条目误加至所有员工对象
问题:考勤条目被错误添加到所有员工对象中
我处理一组考勤JSON数据时遇到了问题:考勤条目确实被添加到了正确的日期和项目下,但所有员工对象的对应项目里都包含了其他员工的考勤条目,而不是只添加到所属员工的对象中。
我的处理逻辑是:
- 遍历响应数据,为每位员工在
employeeList中创建以姓名为键的Employee对象,同时收集所有项目到projectList - 把
projectList添加到dateList的每个日期属性中 - 将带项目列表的
dateList赋值给每位员工的timeentries属性 - 再次遍历响应,把考勤条目添加到对应员工、日期、项目的
timecards数组中
我的代码
let employeeList = {}; let projectList = {}; let dateList = { "2023-02-26": {}, "2023-02-27": {}, "2023-02-28": {}, "2023-03-01": {}, }; class Employee { constructor(name, qbid) { this.startdate = '2023-02-26'; this.enddate = '2023-03-01'; this.fname = ""; this.lname = ""; this.name = name; this.qbid = qbid; this.timeentries = []; } } function processData(res) { //create employee objects for each employee timeentry[155].value is a name text value "Last, First" res.data.forEach((timeentry) => { employeeList[timeentry[155].value] = new Employee(timeentry[155].value,timeentry[160].value); //add all projects to projectList obj. projectList[timeentry[18].value] = { projectname: timeentry[18].value, projectid: timeentry[17].value, timecards: [] } }); //add projectList to each date in dateList for (key in dateList) { dateList[key] = projectList } //add dateList with projectLists to employee.timeentries for (key in employeeList) { employeeList[key].timeentries = dateList; } //add time entry objects to employee,date,project res.data.forEach(timeentry => { employeeList[timeentry[155].value].timeentries[timeentry[23].value][timeentry[18].value].timecards.push(timeentry) }) }
最终生成的Employee对象示例
Last, First: { fname: 'First', lname: 'Last', timeentries: { 2023-03-01: { project1:{ timecards:[JSON Object] }, project2:{ timecards:[JSON Object] } }, 2023-03-02: { project1:{ timecards:[JSON Object] }, project2:{ timecards:[JSON Object] } } } }
问题原因
JavaScript中对象是引用类型,你的代码里犯了两个关键的引用复用错误:
- 把
projectList直接赋值给dateList的每个日期属性——所有日期都指向同一个projectList对象,而非各自拥有独立的项目列表 - 把
dateList直接赋值给每个员工的timeentries属性——所有员工的timeentries都指向同一个dateList对象
这意味着,当你给某一位员工的某个项目添加考勤条目时,实际上是在修改那个共享的projectList里的timecards数组,所有引用这个对象的员工都会看到这个变化。
解决思路
核心是为每个日期、每个员工创建独立的对象副本,而非复用同一个引用:
- 为
dateList的每个日期生成独立的项目对象(每个项目的timecards都是新数组) - 为每个员工的
timeentries创建专属的日期-项目结构,确保员工间的对象互不关联
修正后的代码
let employeeList = {}; let projectList = {}; let dateList = { "2023-02-26": {}, "2023-02-27": {}, "2023-02-28": {}, "2023-03-01": {}, }; class Employee { constructor(name, qbid) { this.startdate = '2023-02-26'; this.enddate = '2023-03-01'; this.fname = ""; this.lname = ""; this.name = name; this.qbid = qbid; this.timeentries = {}; // 改为对象类型,匹配dateList结构 } } function processData(res) { // 第一步:收集员工和项目信息(避免重复创建) res.data.forEach((timeentry) => { const empName = timeentry[155].value; if (!employeeList[empName]) { employeeList[empName] = new Employee(empName, timeentry[160].value); } const projName = timeentry[18].value; if (!projectList[projName]) { projectList[projName] = { projectname: projName, projectid: timeentry[17].value, timecards: [] }; } }); // 第二步:为每个员工创建独立的日期-项目结构 for (const empName in employeeList) { const emp = employeeList[empName]; emp.timeentries = {}; for (const dateStr in dateList) { emp.timeentries[dateStr] = {}; // 为每个项目创建独立对象,确保timecards数组不共享 for (const projName in projectList) { emp.timeentries[dateStr][projName] = { ...projectList[projName], timecards: [] }; } } } // 第三步:添加考勤条目到对应员工、日期、项目 res.data.forEach(timeentry => { const empName = timeentry[155].value; const dateStr = timeentry[23].value; const projName = timeentry[18].value; employeeList[empName].timeentries[dateStr][projName].timecards.push(timeentry); }); }
内容的提问来源于stack exchange,提问作者schteev
相关产品推荐
相关产品推荐

