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

JavaScript不使用eval/Function构建遵循优先级的布尔表达式求值

问题答案

完全不需要使用eval或Function,可以通过遵循JavaScript运算符优先级规则的原生逻辑实现安全求值,不存在代码注入风险。

实现原理

JavaScript中逻辑运算符的优先级规则为:&&(逻辑与)优先级高于||(逻辑或)。因此仅包含这两种运算符的布尔表达式,求值顺序可以拆为两步:

  1. 优先计算所有被&&连接的连续布尔值片段,得到每个片段的计算结果
  2. 将所有片段的结果通过||连接计算,得到最终值

以题目给出的表达式true && true || false && false为例:

  • 第一步拆分&&片段计算:true && true结果为true,false && false结果为false
  • 第二步计算或运算:true || false结果为true,和JS原生求值结果完全一致

直接从左到右遍历计算会得到错误结果,本质是提前计算了||之后的&&运算,违反了优先级规则。

具体实现代码

/**
 * 安全计算仅包含&&、||的布尔表达式,无需eval/Function
 * @param {boolean[]} values 布尔值数组
 * @param {('&&'|'||')[]} ops 逻辑运算符数组,长度需比values少1
 * @returns {boolean} 表达式最终求值结果
 */
function safeEvalBoolean(values, ops) {
  // 入组合法性校验
  if (values.length !== ops.length + 1) {
    throw new Error('参数不合法:布尔值数组长度必须比运算符数组长1');
  }

  // 第一步:优先计算所有高优先级的&&运算,按||拆分求值片段
  const orGroups = [values[0]];
  for (let i = 0; i < ops.length; i++) {
    const op = ops[i];
    const nextVal = values[i + 1];
    switch(op) {
      case '&&':
        // &&优先级高,直接和当前分组最后一个值运算后替换,保留短路特性
        orGroups[orGroups.length - 1] = orGroups.at(-1) && nextVal;
        break;
      case '||':
        // ||优先级低,将下一个值作为新分组存入
        orGroups.push(nextVal);
        break;
      default:
        throw new Error(`不支持的运算符:${op}`);
    }
  }

  // 第二步:所有分组结果做||运算,利用some短路特性提升性能
  return orGroups.some(item => item);
}

测试验证

const to_eval = [true, true, false, false];
const ops = ['&&', '||', '&&'];
console.log(safeEvalBoolean(to_eval, ops)); // 输出true,符合JS原生求值结果

扩展说明

该实现完全保留了JS逻辑运算符的短路特性,和原生表达式执行行为完全一致。如果后续需要支持更多运算符(比如逻辑非!、比较运算符、括号等),可以使用调度场算法先将中缀表达式转换为后缀表达式(逆波兰表达式),再通过栈结构求值,整个过程依然是纯数值运算,不需要动态执行代码,同样没有安全风险。对于仅包含&&和||的场景,上述两步法代码最简、性能最高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:45:38