Sonar报Remove this assignment of "k"问题原因及修复咨询
Sonar「Remove this assignment of "k"」告警修复方案
告警触发原因
这条Sonar规则的核心判定逻辑是:禁止在for循环的循环体内部手动修改循环计数器变量。你代码中写在splice后的--k、--l就是触发告警的直接原因。
这种在循环体内篡改计数器的写法属于典型的代码坏味道:可读性差,后续维护时很容易因为忽略计数器的额外修改,引入死循环、索引越界、遍历漏项等隐蔽bug,Sonar不是否定你的业务逻辑,是否定这种高风险的实现方式。
注意:直接删除
--k、--l确实会导致功能异常。因为数组调用splice删除元素后,后续元素会整体前移一位,如果不回退索引,下一轮循环计数器自增后会直接跳过被删位置的新元素,出现菜单权限漏过滤的问题。
正确修复方案
不需要保留手动修改计数器的写法,换用不会产生索引错位问题的遍历逻辑即可,两种常用方案如下,功能和原代码完全一致:
- 方案1:倒序遍历(最小改动)
从数组末尾往前遍历,删除元素时只会影响已经遍历过的尾部索引,不会干扰还没遍历到的前部元素,完全不需要手动修正计数器:
// 外层菜单倒序遍历 for (let k = this.side_list.length - 1; k >= 0; k--) { const currentMenu = this.side_list[k]; if (this.allowedPageList.indexOf(currentMenu.route) === -1) { this.side_list.splice(k, 1); continue; } // 子菜单同样倒序遍历 if (currentMenu.children?.length > 0) { for (let l = currentMenu.children.length - 1; l >= 0; l--) { if (this.allowedPageList.indexOf(currentMenu.children[l].route) === -1) { currentMenu.children.splice(l, 1); } } } }
- 方案2:使用
filter生成新数组(推荐,可读性最高)
直接用数组原生的filter方法做过滤,全程不需要手动操作索引,逻辑更直观,从根源上避免计数器误用的问题:
this.side_list = this.side_list.filter(menu => { // 外层菜单无权限直接过滤 if (this.allowedPageList.indexOf(menu.route) === -1) { return false; } // 过滤子菜单 if (menu.children?.length) { menu.children = menu.children.filter( child => this.allowedPageList.indexOf(child.route) !== -1 ); } return true; });
两种写法都可以直接消除Sonar告警,同时不会破坏原有的侧边栏权限过滤逻辑。
内容的提问来源于stack exchange,提问作者Aurazo Script
相关产品推荐
相关产品推荐

