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

计算器项目替换eval()函数实现计算功能的技术咨询

替换计算器中的eval()函数方案

要替换eval()同时保留计算功能,核心是避免执行任意代码的安全风险,同时正确解析数学表达式。下面提供两种可行的实现方式:

方案一:手动实现四则运算解析(推荐,安全可控)

手动解析表达式能完全掌控输入逻辑,彻底规避代码注入风险。以下是支持加减乘除取模且遵循运算符优先级的实现:

首先添加一个解析计算的函数:

function calculateExpression(expression) {
    // 过滤非法字符
    const sanitized = expression.replace(/[^0-9+\-*/% .]/g, '');
    // 校验表达式首尾是否为运算符
    if (/^[+\-*/%]/.test(sanitized) || /[+\-*/%]$/.test(sanitized)) {
        throw new Error('Invalid expression');
    }

    // 拆分数字和运算符为数组
    const tokens = sanitized.match(/(\d+\.?\d*|[+\-*/%])/g);
    if (!tokens) throw new Error('Invalid expression');

    // 第一步:处理乘、除、取模(优先级更高)
    let i = 0;
    while (i < tokens.length) {
        const token = tokens[i];
        if (token === '*' || token === '/' || token === '%') {
            const left = parseFloat(tokens[i-1]);
            const right = parseFloat(tokens[i+1]);
            let result;
            switch(token) {
                case '*': result = left * right; break;
                case '/': 
                    if (right === 0) throw new Error('Division by zero');
                    result = left / right; 
                    break;
                case '%': result = left % right; break;
            }
            // 替换运算的三个元素为计算结果
            tokens.splice(i-1, 3, result.toString());
            i -= 1; // 回退索引,重新检查当前位置
        } else {
            i++;
        }
    }

    // 第二步:处理加、减
    let result = parseFloat(tokens[0]);
    for (let i = 1; i < tokens.length; i += 2) {
        const operator = tokens[i];
        const num = parseFloat(tokens[i+1]);
        switch(operator) {
            case '+': result += num; break;
            case '-': result -= num; break;
        }
    }

    return result;
}

然后修改你的calBtn点击事件:

calBtn.addEventListener('click',()=>{
    try{
        console.log("Input value:", userInput.value);
        const result = calculateExpression(userInput.value);
        userOutput.value = isNaN(result) ? 'Invalid selection' : result;
    }
    catch(e){
        userOutput.value='Invalid selection';
    }
});

方案二:使用Function构造函数(简单但需严格校验)

如果不想手动解析,可以用Function替代eval,但必须做严格的输入过滤,仅允许合法的数字和运算符:

calBtn.addEventListener('click',()=>{
    try{
        console.log("Input value:", userInput.value);
        // 只保留数字、运算符、小数点和空格
        const sanitizedInput = userInput.value.replace(/[^0-9+\-*/% .]/g, '');
        // 额外校验:禁止开头/结尾是运算符、禁止连续运算符
        if (/^[+\-*/%]/.test(sanitizedInput) || /[+\-*/%]{2,}/.test(sanitizedInput) || /[+\-*/%]$/.test(sanitizedInput)) {
            throw new Error('Invalid expression');
        }
        // 创建函数并执行计算
        const calculate = new Function(`return ${sanitizedInput}`);
        const result = calculate();
        userOutput.value = isNaN(result) ? 'Invalid selection' : result;
    }
    catch(e){
        userOutput.value='Invalid selection';
    }
});

额外优化建议

  • 输入实时校验:在按钮点击时就拦截非法输入,比如不允许连续点击运算符,避免用户输入无效格式
  • 补充小数点按钮:添加小数点按钮并设置data-type="number",完善计算器功能
  • 处理精度问题:浮点数计算可能存在精度误差,可以用toFixed(n)控制结果显示的小数位数

内容的提问来源于stack exchange,提问作者Adarsh tripathi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:16:08