JavaScript合并camData的Events字段时属性保留及长度异常问题
循环赋值后Events长度未更新的原因
- 你之前编写的
map方法返回值本身就是concat拼接完成的纯事件数组,所以camEvents的结构是[Array(200), Array(200), ...],每个元素是直接装事件的一维数组,不存在.Events属性。 - 循环中执行
data.camData[i].Events = camEvents[i].Events时,等号右侧取到的值是undefined,给对象属性赋值undefined不会覆盖原有已存在的数组引用,因此data.camData里的Events还是最初长度为100的原数组,长度自然不会变化。 - 额外的隐藏问题:你给出的数组结构中摄像头ID字段名是
CamId(末位字母小写),但map逻辑中写的是camData.CamID(末位字母大写),字段名不匹配会导致拿不到state中对应摄像头的数据,concat时会把undefined拼入数组,引发后续异常。
正确实现方案
根据需求(保留data.camData所有原有字段,仅合并对应摄像头的Events),推荐两种可直接运行的写法:
写法1:生成新的合并后数组(不修改原data数据,适合不可变数据场景)
直接在map中展开原摄像头对象的所有属性,仅替换Events字段为合并后的结果:
const mergedCamData = data.camData.map(cam => { // 按CamId匹配state中对应的摄像头数据,兼容找不到的空场景 const targetStateCam = state.camData.find(item => item.CamId === cam.CamId) || {} return { ...cam, // 保留CamId、LastStatus等所有原有字段 Events: [...cam.Events, ...(targetStateCam.Events || [])] // 合并两边Events,做空值兜底 } })
执行后mergedCamData[0].Events.length即为200,且其他字段完整保留。
写法2:直接修改原data.camData(不需要生成新数组,适合允许修改原数据的场景)
不需要额外定义中间变量存储拼接结果,直接遍历原数组追加Events即可:
data.camData.forEach(cam => { const targetStateCam = state.camData.find(item => item.CamId === cam.CamId) if (targetStateCam?.Events?.length) { // 直接把对应摄像头的state侧Events追加到原数组中 cam.Events.push(...targetStateCam.Events) } })
执行完后直接读取data.camData[0].Events.length就能得到预期的200。
注意:如果能100%确定两个数组的摄像头顺序完全一致、索引一一对应,也可以直接按下标取值匹配,但业务场景下优先用CamId做匹配,避免顺序错位导致数据合并错误。
内容的提问来源于stack exchange,提问作者Yujin Dong
相关产品推荐
相关产品推荐

