2012-05-14 69 views
5

类似python: make a variable equal an operator (+,/,*,-)有没有办法让比较运算符变成一个变量?

我必须要运行一段代码,用户可以选择一个类型的比较,并进行比较的一个值。我很好奇,想知道是否有在Javascript任何方式把用户提供的比较值转换成实际值的比较,让我做这样的事情:

if (user_comparison = '<') { 
    if (user_val < other_val) { 
     do_something(); 
    } 
else if (user_comparison = '<=') { 
    if (user_val <= other_val) { 
     do_something(); 
    } 
....etc 
:而不必做类似的

if (user_val user_comparison other_val) { 
    do_something(); 
} 

请注意,如果任何比较匹配,则会执行相同的代码。

+0

nope,你不能这样做在JS –

回答

10

没有那是不可能的。但是你可以更好地构建你的代码。例如,你可以有一个查找表:

var operator_table = { 
    '>': function(a, b) { return a > b; }, 
    '<': function(a, b) { return a < b; } 
    // ... 
}; 

及更高版本:

if(operator_table[user_comparison](user_val, other_val)) { 
    // do something 
} 

当然,你也应该处理的情况下,当user_comparison不存在于表中。

这些还可以让您更好地控制允许和不允许的操作员。

这是DEMO创建@Jesse

+2

这是一个jsFiddle演示这个:http://jsfiddle.net/jonypawks/Cq8Hd/ – Jesse

+0

为什么downvote? –

+0

谁知道?这是一个不错的,优雅的解决方案,比交换机效果更好。我使用类似的技术在我的应用程序中切换视图。 –

4

假设您正在检查用户提供的操作数和操作符以确保它们包含所需的数据而不是其他JavaScript可执行代码,那么可以将两个操作数与操作符连接在一起,然后将其提供给eval()以获得它执行。

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

所有的输入是邪恶的,直到证明,否则。

此外,请注意,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(); 
} 

注意验证对一个白名单输入几乎总是比它验证对黑名单更好的主意。请参阅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) 

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

+0

你不应该使用eval。 – Jesse

+0

如果这些值中的任何一个是由用户提供的,那么他可以执行任何操作...... –

+0

@Jesse你能解释一下为什么你不应该使用eval吗? – Esen

-1

由于@Susam Pal代码不起作用。我发布一个工作版本

<html> 
    <head> 
    <script> 
     function CompareSomething(val1, compareString, val2) { 
      eval('if(' + val1 + ' ' + compareString + ' ' + val2 + '){conditionPassed();}else{conditionFailed();}'); 
    } 
    function compare(a, op, b) { 
     if (eval(a + op + b)) 
      conditionPassed(); 
     else 
     conditionFailed(); 
    } 
    function conditionPassed() { 
     alert('condition passed'); 
    } 
    function conditionFailed() { 
     alert('condition failed'); 
    } 
    </script> 
    </head> 
<body> 
a:<input id='txt1' type="text" />&nbsp;op:<input id='txt2' type="text" />&nbsp;b:<input id='txt3' type="text" /><br/> 
<button id='compare' onclick='CompareSomething(document.getElementById("txt1").value,document.getElementById("txt2").value,document.getElementById("txt3").value)'>Compare Esen Method</button><br/> 
<button id='compare' onclick='Compare(document.getElementById("txt1").value,document.getElementById("txt2").value,document.getElementById("txt3").value)'>Compare Susam Method</button> 
    </body> 
</html> 
+1

我已经测试了我的代码(http://jsfiddle.net/YrQ4C/)在Firefox,Chrome在Linux以及Windows上,以及IE8,它可以在所有三种浏览器上运行。当我的代码不适合你时,你使用了哪个浏览器?您在JavaScript控制台中遇到了什么错误? –

+0

你已编辑你的答案。你的早期版本有这个代码。试试看,并告诉我这是否适用于所有浏览器。如果我看到您的修改,我不会发布更新的版本。如果这让你烦恼并减少投票,那么非常感谢你。 (eval(a + b)) do_something() – Esen

+1

如果你检查我当前的代码,它有你提到的代码if(eval(a + op) + b))doSomething();'。这是我的第一个不完整答案中的代码。稍后,我添加了只添加了安全检查,以确保解决方案是完整的。你还没有告诉我哪个浏览器不能执行'if(eval(a + op + b))doSomething();'。我目前的解决方案中的这段代码在所有三种浏览器中执行。 –

相关问题