JavaScript对象内数组元素推送异常问题排查与解决
问题:服务状态数据分类错误,所有服务共享同一数组
原始数据与预期结果
有如下结构化payload数据:
var payload = [ { "firstService-2xx": 0.1, "firstService-4xx": 0, "firstService-5xx": 1.2, "secondService-2xx": 5.4, "secondService-4xx": 1, "secondService-5xx": 0.2 }, { "firstService-2xx": 10.4, "firstService-4xx": 0.3, "firstService-5xx": 0.2, "secondService-2xx": 9.8, "secondService-4xx": 0.1, "secondService-5xx": 0.7 } ]
服务名称数组:
var services = ["firstService", "secondService"]
预期处理后得到的结果:
finalResult = { "firstService": { twoHundred: [0.1, 10.4], fourHundred: [0, 0.3], fiveHundred: [1.2, 0.2] }, "secondService": { twoHundred: [5.4, 9.8], fourHundred: [1, 0.1], fiveHundred: [0.2, 0.7] } }
错误现象与原因
初始化目标结构时使用了如下代码:
var obj = { twoHundred: [], fourHundred: [], fiveHundred: [] }; var finalResult = { "firstService" : obj, "secondService": obj }
之后执行数据分类逻辑,发现所有服务的数组都被填充了全部数据,比如:
{ firstService: { twoHundred: [ 0.1, 5.4, 10.4, 9.8 ], fourHundred: [ 0, 1, 0.3, 0.1 ], fiveHundred: [ 1.2, 0.2, 0.2, 0.7 ] }, secondService: { twoHundred: [ 0.1, 5.4, 10.4, 9.8 ], fourHundred: [ 0, 1, 0.3, 0.1 ], fiveHundred: [ 1.2, 0.2, 0.2, 0.7 ] } }
核心原因:JavaScript中对象是引用类型,finalResult里的firstService和secondService都指向同一个obj对象。所以不管修改哪个服务下的数组,本质都是修改同一个数组,导致所有服务共享数据。
解决方案
1. 正确初始化finalResult
给每个服务创建独立的状态数组对象,避免引用共享:
// 直接初始化(服务数量少的情况) var finalResult = { "firstService": { twoHundred: [], fourHundred: [], fiveHundred: [] }, "secondService": { twoHundred: [], fourHundred: [], fiveHundred: [] } }; // 或循环动态生成(适合服务数量较多的场景) // var finalResult = {}; // services.forEach(service => { // finalResult[service] = { twoHundred: [], fourHundred: [], fiveHundred: [] }; // });
2. 优化数据分类逻辑
直接从payload的键中拆分服务名和状态码,简化嵌套循环:
payload.forEach(element => { for (const [key, value] of Object.entries(element)) { // 拆分服务名与状态码 const [service, status] = key.split('-'); // 根据状态码匹配对应数组 switch(status) { case '2xx': finalResult[service].twoHundred.push(value); break; case '4xx': finalResult[service].fourHundred.push(value); break; case '5xx': finalResult[service].fiveHundred.push(value); break; } } });
完整正确代码
var payload = [ { "firstService-2xx": 0.1, "firstService-4xx": 0, "firstService-5xx": 1.2, "secondService-2xx": 5.4, "secondService-4xx": 1, "secondService-5xx": 0.2 }, { "firstService-2xx": 10.4, "firstService-4xx": 0.3, "firstService-5xx": 0.2, "secondService-2xx": 9.8, "secondService-4xx": 0.1, "secondService-5xx": 0.7 } ]; var services = ["firstService", "secondService"]; // 初始化每个服务的独立状态数组 var finalResult = {}; services.forEach(service => { finalResult[service] = { twoHundred: [], fourHundred: [], fiveHundred: [] }; }); // 处理数据分类 payload.forEach(element => { for (const [key, value] of Object.entries(element)) { const [service, status] = key.split('-'); switch(status) { case '2xx': finalResult[service].twoHundred.push(value); break; case '4xx': finalResult[service].fourHundred.push(value); break; case '5xx': finalResult[service].fiveHundred.push(value); break; } } }); console.log(finalResult);
执行后就能得到预期的正确结果,每个服务的状态数组只包含自身对应的数据。
内容的提问来源于stack exchange,提问作者William.P
相关产品推荐
相关产品推荐

