React计算器App中eval函数的低侵入式替代方案求助
替代React计算器中eval的轻量方案
你可以用以下两种方案替换eval,无需大幅修改现有代码:
方案一:使用new Function替代(最小改动)
new Function比eval更安全(它在全局作用域执行,而非当前函数作用域),用法和eval几乎一致,直接替换calculate函数即可:
修改后的calculate函数:
function calculate() { try { // 用new Function替代eval,同时处理表达式逻辑 const result = new Function('return ' + value)(); setDisp(result); setValue(String(result)); // 将结果转为字符串,方便后续继续计算 } catch (err) { setDisp("ERROR"); } }
同时建议完善errorCatch函数,在输入阶段就拦截无效表达式,减少计算时的错误:
function errorCatch() { setValue(prevState => { const lastChar = prevState.slice(-1); const isOperator = ['+', '-', '*', '/'].includes(lastChar); // 拦截连续运算符、空值时输入非负号运算符的情况 if ((isOperator && ['+', '-', '*', '/'].includes(prevState.slice(-2, -1))) || (prevState === "" && isOperator && lastChar !== '-')) { setDisp("ERROR"); return prevState.slice(0, -1); // 移除最后输入的无效运算符 } else if (prevState.length > 20) { setDisp("MAX LIMIT REACHED"); return prevState; } return prevState; }); }
方案二:自定义简单表达式解析器(更安全)
如果想完全避免动态代码执行的风险,可以自己写一个仅处理加减乘除和小数的解析器,逻辑简单,且不用改动其他组件:
先在App组件中添加解析函数:
function parseExpression(expr) { // 处理负号场景,比如"-3+5"或"3*-2" expr = expr.replace(/(\d)(-)(\d)/g, '$1+-$3'); expr = expr.startsWith('-') ? '0' + expr : expr; // 先拆分加减项,逐个处理乘除 const addSubTerms = expr.split(/([+-])/); let finalResult = handleMultiplyDivide(addSubTerms[0]); for (let i = 1; i < addSubTerms.length; i += 2) { const operator = addSubTerms[i]; const termResult = handleMultiplyDivide(addSubTerms[i+1]); if (isNaN(termResult)) return NaN; if (operator === '+') finalResult += termResult; else finalResult -= termResult; } return finalResult; // 处理单个项内的乘除运算 function handleMultiplyDivide(term) { const parts = term.split(/([\*\/])/); let result = parseFloat(parts[0]); for (let i = 1; i < parts.length; i += 2) { const op = parts[i]; const num = parseFloat(parts[i+1]); if (isNaN(num)) return NaN; if (op === '*') result *= num; else if (op === '/') { if (num === 0) return NaN; // 拦截除零错误 result /= num; } } return result; } }
然后修改calculate函数:
function calculate() { const result = parseExpression(value); if (isNaN(result)) { setDisp("ERROR"); } else { setDisp(result); setValue(String(result)); } }
这个解析器仅处理你的计算器支持的运算,完全避免了动态代码执行的安全风险,同时无需改动Buttons等其他组件的代码。
内容的提问来源于stack exchange,提问作者Anukrati Mehta
相关产品推荐
相关产品推荐

