如何替换旧树形菜单代码中的eval函数以解决安全问题
嘿,兄弟!看到你在更新旧树形菜单、想换掉eval函数来解决安全问题,而且这是你第一次发帖,必须给你支支招~
首先得说为啥要换掉eval():这货会把传入的字符串当成代码执行,要是不小心混入了恶意代码(比如用户输入的危险内容),安全风险简直拉满,所以换掉它绝对是正确的选择。结合你给出的代码片段(正在处理树形节点的parse函数),我猜你的eval大概率用在这几个场景里,给你对应的替换方案:
1. 如果是用eval解析JSON数据
很多旧代码会用eval('(' + jsonStr + ')')来解析后端返回的树形数据,这是最常见的eval用法。直接换成原生的JSON.parse()就好,它只解析标准的JSON格式,不会执行任何代码,安全又高效:
// 原来的写法 // const treeData = eval('(' + rawData + ')'); // 替换后的写法 const treeData = JSON.parse(rawData);
2. 如果是用eval动态调用函数
要是原来的代码用eval来根据字符串调用不同的菜单操作函数(比如打开、关闭菜单),可以用函数映射对象来替代:
// 先把所有菜单相关的函数存到一个对象里 const menuActions = { openSection: (menuId) => { // 原来openSection函数的逻辑,比如给节点加className document.getElementById(menuId).classList.add('open'); }, closeSection: (menuId) => { document.getElementById(menuId).classList.remove('open'); } }; // 原来的eval写法 // eval(actionName + '("' + menuId + '")'); // 替换后的写法 if (menuActions[actionName]) { menuActions[actionName](menuId); }
这种方式不仅安全,代码可读性也更高,还能避免拼写错误导致的意外执行。
3. 如果是用eval动态生成DOM代码
要是原来用eval来执行创建DOM节点的字符串,那直接用原生DOM API来实现就好,比如createElement、appendChild:
// 原来的eval写法 // eval('document.getElementById("' + parentId + '").innerHTML += "<li>" + text + "</li>"'); // 替换后的写法 const parentNode = document.getElementById(parentId); const liNode = document.createElement('li'); liNode.textContent = text; // 用textContent避免XSS风险 parentNode.appendChild(liNode);
要是需要更复杂的结构,也可以用模板字符串配合innerHTML,但一定要确保插入的内容是安全的(比如不要直接用未过滤的用户输入内容)。
结合你的parse函数的小建议
看你给出的parse函数正在遍历li节点、设置id和处理子ul,要是原来在这段逻辑里用了eval(比如动态获取节点属性或者处理子节点数据),可以直接改成属性访问或者数组操作。比如原来的eval('nodes[' + i + '].getAttribute("data-key")'),直接换成nodes[i].getAttribute('data-key')就好,完全不需要eval。
最后提醒一句:替换完之后一定要多测试几个场景,确保原来的树形菜单展开、折叠、跳转等功能都正常工作,毕竟旧代码可能藏着一些你没注意到的eval用法~
备注:内容来源于stack exchange,提问作者Mattia Oppedisano

