有没有办法让比较运算符成为变量?

lig*_*ike 6 javascript comparison operators

python类似:使变量等于运算符(+,/,*, - )

我有一些代码,用户可以选择要运行的比较类型,以及要比较的值.我很想知道Javascript中是否有任何方法可以将用户提供的比较值转换为实际比较,这样我就可以执行以下操作:

if (user_val user_comparison other_val) {
    do_something();
}
Run Code Online (Sandbox Code Playgroud)

而不必像以下那样做:

if (user_comparison = '<') {
    if (user_val < other_val) {
        do_something();
    }
else if (user_comparison = '<=') {
    if (user_val <= other_val) {
        do_something();
    }
....etc
Run Code Online (Sandbox Code Playgroud)

请注意,如果匹配任何比较,将执行相同的代码.

Fel*_*ing 14

不,这是不可能的.但是您可以更好地构建代码.例如,您可以拥有一个查找表:

var operator_table = {
    '>': function(a, b) { return a > b; },
    '<': function(a, b) { return a < b; }
    // ...
};
Run Code Online (Sandbox Code Playgroud)

然后:

if(operator_table[user_comparison](user_val, other_val)) {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

当然,您还应该处理user_comparison表中不存在的情况.

这些还可以让您更好地控制允许和不允许的运算符.

这是@Jesse创作的DEMO.

  • 这是一个jsFiddle演示这个:http://jsfiddle.net/jonypawks/Cq8Hd/ (2认同)

Sus*_*Pal 5

假设您正在检查用户提供的操作数和运算符以确保它们包含您想要的数据而不是其他javascript可执行代码,您可以将两个操作数与运算符连接在一起并将其提供给它以eval()使其执行.

现在,这eval()危险,因为它可以执行任何JavaScript代码.用户可以作为运营商提供可执行的和可能是恶意的JavaScript代码,并eval()对其进行评估.因此,在进行连接时,应在验证操作数是否安全后执行此操作.为了强调这一点,我将用大字体编写一个最重要的计算机安全原则:

除非另有证明,所有输入都是邪恶的

另外,请注意eval()调用JavaScript解释器来解释,编译和执行代码.这很慢.如果你eval()偶尔使用一次,你可能没有注意到任何可观察到的性能问题,如果你eval()经常在每个关键事件上打电话,你可能会注意到性能问题.

考虑到这些缺点eval(),你可能想要寻找一个更好的解决方案,如Felix Kling发布的解决方案.但是,也可以使用eval()如下所示的安全方式解决此问题:

function compare(a, op, b)
{
  // Check that we have two numbers and an operator fed as a string.
  if (typeof a != 'number' || typeof b != 'number' || typeof op != 'string')
    return

  // Make sure that the string doesn't contain any executable code by checking
  // it against a whitelist of allowed comparison operators.
  if (['<', '>', '<=', '>=', '==', '!='].indexOf(op) == -1)
    return

  // If we have reached here, we are sure that a and b are two integers and
  // op contains a valid comparison operator. It is now safe to concatenate
  // them and make a JavaScript executable code.
  if (eval(a + op + b))
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

请注意,针对白名单验证输入几乎总是比针对黑名单验证它更好.有关它的简要讨论,请参阅https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet#White_List_Input_Validation.

以下是此解决方案的演示:http://jsfiddle.net/YrQ4C/(代码也转载如下):

function doSomething()
{
  alert('done something!')
}

function compare(a, op, b)
{
  if (typeof a != 'number' || typeof b != 'number' || typeof op != 'string')
    return

  if (['<', '>', '<=', '>=', '==', '!='].indexOf(op) == -1)
    return

  if (eval(a + op + b))
    doSomething();
}

// Positive test cases
compare(2, '<', 3)
compare(2, '<=', 3)

// Negative test cases
compare(2, '>', 3)
compare(2, '>=', 3)

// Attack tests
compare('alert(', '"attack!"', ')')

// Edit: Adding a new attack test case given by Jesse
// in the comments below. This function prevents this
// attack successfully because the whitelist validation
// for the second argument would fail.
compare(1, ';console.log("executed code");2==', 2)
Run Code Online (Sandbox Code Playgroud)

编辑:演示与杰西的测试案例包括:http://jsfiddle.net/99eP2/