0

Let's say we have this kind of code:

var movement = setInterval(function() {
    var position = 0; // Just some example values
    var limit = 200;  // to go with the code below

    if (position < limit) {
        position = position + 10;
    }
}, 500);

Is it possible to replace the < sign in position < limit and the + sign in position + 10 with a variable (so that the code works of course) ?

And if it is, what's the best way to do it ?

Kaloyan
  • 7,262
  • 4
  • 32
  • 47
  • possible duplicate of [jQuery if statement with variable mathematical operator](http://stackoverflow.com/questions/12961085/jquery-if-statement-with-variable-mathematical-operator) or [Is there a way to make a comparison operator a variable?](http://stackoverflow.com/questions/12961085/jquery-if-statement-with-variable-mathematical-operator) – Bergi Jun 01 '13 at 18:07

4 Answers4

7

Not exactly but you could use a map of functions :

var comparators = {
    '<': function(a,b){return a<b},
    '<=': function(a,b){return a<=b}
};
var operators = {
    '+': function(a,b){return a+b},
    '/': function(a,b){return a/b}
};

var cp = '<', op = '+';
if (comparators[op](position, limit)) {
     position = operators[op](position, 10);
}

You could also keep the function in your variable :

var cp = comparators['<'];
if (cp(position, limit)) {
    ...

Aside : if you like to keep your code as DRY as possible, you may generate the functions, for example for the operators :

var operators = {};
'+*/-'.split('').forEach(function(v){
  operators[v]=eval('(function(a,b){return a'+v+'b})');
});

OK, it's mostly for fun :)

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • I just did something similar, by putting every condition and position increase/decrease in an object and then using `eval()`. I know in general eval is evil, but in this case it should work I guess. I was indeed trying to make the code as dry as possible. :) – Kaloyan Jun 01 '13 at 16:43
  • Contrary to popular belief (mostly a meme, in fact), eval is **not** evil. You just must not do stupid things with it, like evaluating any string. It's slow though, which is why in the code I suggest I only use it for the map initialization, not after. – Denys Séguret Jun 01 '13 at 16:46
  • Truly slow, I do however dig your original answer. Nice idea. – Gabe Jun 01 '13 at 16:47
  • 1
    +1 for the wise use of `eval()` here. _With great power comes great responsibility_. – moonwave99 Jun 01 '13 at 16:48
  • Oh, i didn't saw your eval method before posting my answer :( – A. Wolff Jun 01 '13 at 16:49
  • 1
    I think this is another case where `new Function('a', 'b', 'return a'+v+'b;')` would have been more appropriate :-) [(see implementation)](http://stackoverflow.com/a/12961206/1048572) – Bergi Jun 01 '13 at 18:05
  • @Bergi totally right, even if it does exactly the same thing it's prettier. I always forget this one... – Denys Séguret Jun 01 '13 at 18:11
  • @dystroy: The parent scope of the `new Function` would be different actually - that's why I don't like `eval` :-) – Bergi Jun 01 '13 at 18:13
1

Create a function such as:

function process(left, op, right){
     var result;
     if(op == ">")
       result = left > right;
     else if(op == "<")
       result = left < right;
     else if(op == "+")
       result = left + right;
     else if(op == "-")
       result = left - right;
     return result;
}

if (process(position, "<", limit)) {
    position = process(position, "+", 10);
}
Gabe
  • 49,577
  • 28
  • 142
  • 181
1

< and + are just binary operators so you could treat them a calls to a function with two arguments.

E.g.:

var movement = setInterval(function() {
    var position = 0; // Just some example values
    var limit = 200;  // to go with the code below

    if (func1(position, limit)) {
        position = func2(position, 10);
    }
}, 500);

and then func1 and func2 can be defined however you like, or even be variables that point to functions.

E.g.:

var func1 = function(leftHandSide, rightHandSide) {
   return leftHandSize < rightHandSide;
}
Matt Wonlaw
  • 12,146
  • 5
  • 42
  • 44
1

This could be an other way i think:

http://jsfiddle.net/D9yqK/

var position = 0; 
var limit = 200; 
var x = '<'; // == , >= , <=, etc...
if(new Function('return '+position+x+limit)()) alert('ok');
A. Wolff
  • 74,033
  • 9
  • 94
  • 155
  • I am so paranoid that I always separate consecutive vars with empty strings so they don't try to add up or something `"return "+position+""+x+""+limit+";"`, but is totally unnecessary since `x` will be a string 100% of the time – ajax333221 Jun 01 '13 at 16:50
  • @ajax333221 my first thought was quite the same as you :=) – A. Wolff Jun 01 '13 at 16:53
  • Instead of creating a function object that is never reused (and stringificating the operands) `eval` would have been simpler here… – Bergi Jun 01 '13 at 18:10