Are Variable Operators Possible?
Asked Answered
G

8

110

Is there a way to do something similar to either of the following:

var1 = 10; var2 = 20;
var operator = "<";
console.log(var1 operator var2); // returns true

-- OR --

var1 = 10; var2 = 20;
var operator = "+";
total = var1 operator var2; // total === 30
Gunfire answered 29/4, 2011 at 15:53 Comment(0)
F
219

Not out of the box. However, it's easy to build by hand in many languages including JS.

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

var op = '+';
alert(operators[op](10, 20));

You can use ascii-based names like plus, to avoid going through strings if you don't need to. However, half of the questions similar to this one were asked because someone had strings representing operators and wanted functions from them.

Fechter answered 29/4, 2011 at 16:4 Comment(0)
G
12

We can implement this using eval, since we are using it for operator checking.

var number1 = 30;
var number2 = 40;
var operator = '===';

function evaluate(param1, param2, operator) {
  return eval(param1 + operator + param2);
}

if (evaluate(number1, number2, operator)) {}

in this way we can use dynamic operator evaluation.

Gide answered 29/5, 2014 at 5:13 Comment(2)
Thank you!!!!!!!! I like this approach. Much cleanerMussel
Big security risk - developer.mozilla.org/en-US/docs/web/javascript/reference/…!Taka
F
10

You can use the eval() function, but that is not a good idea. I think the better way is writing functions for your operators like this:

var addition = function(first, second) {
   return first+second;
};

var subtraction = function(first, second) {
   return first-second;
};

var operator = addition;

alert(operator(12, 13));

var operator = subtraction;

alert(operator(12, 13));
Finsen answered 29/4, 2011 at 16:1 Comment(0)
K
10

I believe you want a variable operator. here's one, created as object. you can change the current operation by changing:

[yourObjectName].operation = "<" //changes operation to less than


function VarOperator(op) { //you object containing your operator
    this.operation = op;

    this.evaluate = function evaluate(param1, param2) {
        switch(this.operation) {
            case "+":
                return param1 + param2;
            case "-":
                return param1 - param2;
            case "*":
                return param1 * param2;
            case "/":
                return param1 / param2;
            case "<":
                return param1 < param2;
            case ">":
                return param1 > param2;
        }
    }
}

//sample usage:
var vo = new VarOperator("+"); //initial operation: addition
vo.evaluate(21,5); // returns 26
vo.operation = "-" // new operation: subtraction
vo.evaluate(21,5); //returns 16
vo.operation = ">" //new operation: ">"
vo.evaluate(21,5); //returns true
Kylakylah answered 29/4, 2011 at 16:11 Comment(0)
U
9

A bit newer approach. It can be done pretty decent using currying:

const calculate = a => str => b => {switch(str) {
  case '+': return a + b
  case '-': return a - b
  case '/': return a / b
  case '*': return a * b
  default: return 'Invalid operation'
}}

const res = calculate(15)('*')(28)

console.log('15 * 28 =', res)
Umpteen answered 25/5, 2021 at 18:5 Comment(1)
Very functional and Spicy Curry.Estimate
L
2

You can't overload operators in JavaScript. You can off course use functions to help

var plus = function(a, b) {
    return a + b;
};

var smaller = function(a, b) { 
    return a < b;
};

var operator = plus;
var total = operator(a, b);
operator = smaller;
if(operator(var1, var2)){ /*do something*/ }
Lore answered 29/4, 2011 at 16:1 Comment(0)
J
2

From another answer I recently posted, this is in V8 and I think JavaScriptCore, but not Firefox and it's not spec. Since you can trap the operation and the comparators you can implement operator native overloading in most situations with a bit of work.

var actions = [];
var overload = {
  valueOf: function(){
    var caller = arguments.callee.caller;
    actions.push({
      operation: caller.name,
      left: caller.arguments[0] === this ? "unknown" : this,
      right: caller.arguments[0]
    });
    return Object.prototype.toString.call(this);
  }
};
overload.toString = overload.valueOf;
overload == 10;
overload === 10;
overload * 10;
10 / overload;
overload in window;
-overload;
+overload;
overload < 5;
overload > 5;
[][overload];
overload == overload;
console.log(actions);

Output:

[ { operation: 'EQUALS',
    left: overload,
    right: 10 },
  { operation: 'MUL',
    left: overload,
    right: 10 },
  { operation: 'DIV',
    left: 'unknown',
    right: overload },
  { operation: 'IN',
    left: overload,
    right: DOMWindow },
  { operation: 'UNARY_MINUS',
    left: overload,
    right: undefined },
  { operation: 'TO_NUMBER',
    left: overload,
    right: undefined },
  { operation: 'COMPARE',
    left: overload,
    right: 5 },
  { operation: 'COMPARE',
    left: 'unknown',
    right: overload },
  { operation: 'ToString',
    left: 'unknown',
    right: overload } ]

At this point you have all the inputs and the operation so the remaining part is the result of the operation. The receiver of the operation will get a primitive value, either string or number, and you can't prevent this. If it's not an arbitrary reciever, say an instance of the class you've operator overloaded, you can handle various get/set traps to intercept the incoming value/prevent overwriting. You can store the operands and operation in some central lookup and use a simple method to trace a primitive value back to the operation which produced it, and then create whatever logic you want to do your custom operation. Another method which would allow arbitrary receivers which could later be reconstituted into complex forms would be in encoding the data into the primitive value so that it can be reversed back into your complex class. Like say an RGB value of 3 distinct 8bit integers (255,255,255) could be be converted into a single number on the get end and the receiver end could trivial convert it back into its complex components. Or for more complex data you could even return a JSON serialized string.

Having access to Harmony Proxies (Firefox6+, Nodejs with flag) makes this whole process immensely easier, as you can create trapping proxies on basically everything and introspect the entire process from end to end and do whatever you want. The operand instances of your data/class, the valueOf/toString/getters of every possible value the internal engine may access, any receiver object you have pre-awareness of, and even trap arbitrary receivers in the case of with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }

Journalist answered 10/11, 2011 at 9:48 Comment(0)
D
1

Copied from puvox-library:

compare(a, b, operator) {
    if(operator === '==') return a == b;
    else if (operator === '===') return a === b;
    else if (operator === '!=') return a != b;
    else if (operator === '!==') return a !== b;
    else if (operator === '>') return a > b;
    else if (operator === '>=') return a >= b;
    else if (operator === '<') return a < b;
    else if (operator === '<=') return a <= b;
    else throw "Unknown operator";
},
calculate(a, b, operator) {
    if(operator === '+') return a + b;
    else if (operator === '-') return a - b;
    else if (operator === '*') return a * b;
    else if (operator === '/') return a / b;
    else if (operator === '%') return a % b;
    else throw "Unknown operator";
},
Distance answered 9/1, 2023 at 12:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.