【问题标题】:Looping variable conditions in an if statement在 if 语句中循环变量条件
【发布时间】:2018-07-02 18:50:27
【问题描述】:

我有很多条件语句存储在一个表中,每个条件语句都有一些截然不同的格式(if x > Yif Z = trueif Z <= 12 等)。我以这样一种方式存储它们,以便我可以轻松地循环遍历条件语句并执行一个函数来更新相关属性。

但是,正如我发现的那样,它不会让我将条件语句存储为变量。意思是,我必须显式声明每个条件语句,而不是声明一次并循环遍历所有可能的条件。

有没有办法做到这一点我错过了,或者根本不理解?

在下面的示例中,我想使用eTable[i].condition 循环遍历存储在该位置的所有条件。这有可能吗?

function checkEvents () {
    eventConditionLength = Object.keys(eTable).length;

    for (let i = 0; i < eventConditionLength; i++) {
        if (eTable[i].condition) {
            alert(i);
        };
    };
};

电子表格

var eTable = {
0: {
        sceneTitle: '', //Descriptive/organizational only
        sceneHeader: ['Event 1', 'Event 1', 'Event 1'],
        sceneImage: ['/images/1.jpg', '/images/2.jpg', '/images/3.jpg'],
        sceneText: ['Test Scene Text 1', 'Test Scene Text 1', 'Test Scene Text 1'],
        sceneControls: ['myFunction1', 'myFunction2', 'myFunction3'],
        visible: false,
        completed: false,
        condition: 'cEvent == "e0002"'
    },
1: {
        sceneTitle: '', //Descriptive/organizational only
        sceneHeader: ['Event 1', 'Event 1', 'Event 1'],
        sceneImage: ['/images/1.jpg', '/images/2.jpg', '/images/3.jpg'],
        sceneText: ['Test Scene Text 1', 'Test Scene Text 1', 'Test Scene Text 1'],
        sceneControls: ['myFunction1', 'myFunction2', 'myFunction3'],
        visible: false,
        completed: false,
        condition: 'stat1 > 15 && completed == false'
    }
};

【问题讨论】:

  • 为什么不直接使用对象数组而不是对象对象?
  • cEventstat1completed 来自哪里?
  • 除了completed,我看不出您的条件与每个对象有何关系。比较的变量在哪里?它们是否在每个对象的外部?如果是这样,您似乎可以存储调用Function 构造函数所需的所有数据(参数名称和函数体),然后创建函数并传入数据。虽然没有更多信息,但很难说。
  • ...如果这不是需要序列化的数据,那么您根本不需要字符串,只需创建函数即可。但同样,在提出合理的解决方案之前需要更多信息。如果不首先尽可能努力地消除为您所拥有的条件存储字符串,我不想继续。
  • 我现在有十几个 JS 文件。仅包括与此处问题相关的位。也就是说,如果您好奇,它通常是一个简单的 RPG 制作工具,具有简化的 UI 布局。这意味着,我的大部分表格都包含 UI 信息。这个特定的表正在生成一个事件模式,它会随着您的决策而动态变化。我正在处理的触发器是触发模态显示的时间/位置,以及何时不显示。一般来说,这些表格尽可能地组织成字面阅读,以便知识有限的人能够阅读。

标签: javascript loops variables if-statement


【解决方案1】:

您可能知道,正如您编写的那样,它总是有效的(只要条件不是空字符串),因为任何非空字符串总是真实的。

最好和最安全的方法是编写某种解析器,它将通过干净地分解并分析条件来分析条件。这些通常看起来像:

const condition = 'x < y';

/**
 * condition is the full string
 * a is the left-hand variable, if needed
 * b is the right-hand variable, if needed
 */
function resolve(condition, a, b) {
  // regex will get the non-alphanumeric operator and the left and right operands
  const [, left, operator, right] = condition.match(/([a-z0-9]+)\s*([^a-z0-9\s]+)\s*([a-z0-9]+)/);
  
  // you'd need a case for each vald operator
  switch (operator) {
    case '<':
      return a < b;
  }
}

console.log(resolve(condition, 3, 5));
console.log(resolve(condition, 5, 3));

显然,这是一个简单的示例,但基本过程是相同的。可能还有一些库可以为您处理它。

那么你可以根据需要使用它:

if (resolve('a > b', a, b)) {
  // do something
}

您还需要一些逻辑来查看操作数是否为数字,如果是,则使用这些值而不是传入的变量。

我不愿提供的另一个选项是使用eval() 函数。这个函数通常是一个非常大、非常糟糕的禁忌,因为它执行任意代码并且可以打开各种安全和逻辑漏洞。但是,对于可能适合的场景(例如供个人使用的非常小的、快速的 Node.js 脚本),值得一提。

const x = 3;
const y = 5;

if (eval('x < y')) {
  console.log('condition hit');
}

这将起作用,在您的示例中,只需将您的 eTable[i].condition 包装在 eval 中(并确保它要查找的变量在当前范围内声明)。

尽管如此,这通常真的不好用,所以如果你使用它,请务必在继续使用它之前阅读所有相关信息。

【讨论】:

  • 谢谢,感谢您的帮助。对于这个项目,重要的是要意识到它对我来说主要是一个学习工具,也许是一个可以玩的玩具。它不存储敏感数据,也不是特别大。在这一点上,我认为 eval() 可以解决问题,但已将其标记在我的列表中,以便在需要时重新评估更大的解决方案。鉴于事情只完成了一半并且缺少很多联系,我认为我现在会继续前进。
【解决方案2】:

您可以使用eval()

function checkEvents () {
    eventConditionLength = Object.keys(eTable).length;


    for (let i = 0; i < eventConditionLength; i++) {
        if (eval(eTable[i].condition))
        {
            alert(i);
        };
    };
};

正如 Vasan 在 cmets 中指出的,有一个 few downsides to eval 需要注意。

【讨论】:

【解决方案3】:

我相信您将字符串传递给 if 条件语句,因为 eTable[i].condition 这不是逻辑条件,它只是字符串(我相信您有字符串)。您需要使用eval() 将您的字符串评估为代码:

for (let i = 0; i < eventConditionLength; i++) {
    if (eval(eTable[i].condition)) {
        alert(i);
    };
};

P.S.: eval() 是糟糕的代码风格并且很危险。小心点。

【讨论】:

    【解决方案4】:

    我可以为你的问题提供 2 个解决方案。

    1. 更好的方法,存储函数。每个函数都会保存你的条件,例如,不是存储eTable['someCondition] = "x &gt; y",而是像eTable['someCondition] = () =&gt; x &gt; y一样存储它,然后你可以通过if (eTable[i].condition()) { /* handle true */ } else { /* handle false */ }简单地调用它。
    2. 不好的方法,使用 eval() 并存储将表示要执行的 js 代码的字符串。

    我认为第一个建议可以实现您的目标。

    【讨论】:

      猜你喜欢
      • 2013-02-11
      • 1970-01-01
      • 1970-01-01
      • 2022-06-21
      • 2022-11-26
      • 2020-04-30
      • 2019-10-22
      • 1970-01-01
      • 2011-09-10
      相关资源
      最近更新 更多