变量运算符可能吗?

时间:2011-04-29 15:53:48

标签: javascript variables operators operator-keyword dynamic-variables

有没有办法做类似于以下任何一种情况:

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

- 或 -

var1 = 10; var2 = 20;
var operator = "+";
total = var1 operator var2; // total === 30

7 个答案:

答案 0 :(得分:138)

没有开箱即用。但是,很容易用包括JS在内的多种语言手工构建。

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

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

您可以使用基于ascii的名称,例如plus,以避免在不需要时浏览字符串。然而,有一半类似于这个问题的问题被问到了,因为有人用字符串表示操作符和想要的函数。

答案 1 :(得分:6)

您可以使用eval()功能,但这不是一个好主意。 我认为更好的方法是为您的运营商编写函数,如下所示:

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));

答案 2 :(得分:5)

我相信你想要一个变量运算符。这是一个,创建为对象。您可以通过更改以下内容来更改当前操作:

[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

答案 3 :(得分:3)

从我最近发布的另一个答案来看,这是在V8中,我认为是JavaScriptCore,但不是Firefox,而且它不是规范。由于您可以捕获操作和比较器,因此您可以在大多数情况下通过一些工作来实现操作符本机重载。

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);

输出:

[ { 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 } ]

此时您拥有所有输入和操作,因此剩余部分是操作的结果。操作的接收器将获得原始值,字符串或数字,您无法阻止这种情况。如果它不是一个任意的接收器,比如你操作员重载的类的实例,你可以处理各种get / set陷阱来拦截传入的值/防止覆盖。您可以将操作数和操作存储在某些中央查找中,并使用一种简单的方法将原始值跟踪回生成它的操作,然后创建您想要执行自定义操作的任何逻辑。允许随后可以重构为复杂形式的任意接收器的另一种方法是将数据编码为原始值,以便可以将其反转回复杂类。比如说,3个不同的8位整数(255,255,255)的RGB值可以在get端转换为单个数字,接收器端可以将其简单地转换回其复杂的组件。或者对于更复杂的数据,您甚至可以返回JSON序列化字符串。

访问Harmony Proxies(Firefox6 +,带有标志的Nodejs)使整个过程变得非常简单,因为您可以基本上在所有内容上创建陷印代理,并从头到尾内省整个过程并执行您想要的任何操作。数据/类的操作数实例,内部引擎可以访问的每个可能值的valueOf / toString / getter,您已预先知晓的任何接收器对象,甚至在with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; } <的情况下捕获任意接收器/ p>

答案 4 :(得分:3)

我们可以使用eval来实现它,因为我们正在使用它来进行运算符检查。

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

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

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

通过这种方式,我们可以使用动态运营商评估。

答案 5 :(得分:2)

您不能在JavaScript中重载运算符。您可以在课程中使用函数来帮助

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*/ }

答案 6 :(得分:1)

有点新的方法。 使用柯里化可以做得相当不错:

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)