You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 02:05:29