Javascript 变量运算符可能吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5834318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:06:54  来源:igfitidea点击:

Are Variable Operators Possible?

javascriptvariablesoperatorsoperator-keyworddynamic-variables

提问by Gary

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

回答by

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

不是开箱即用的。但是,在包括 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.

plus如果不需要,您可以使用基于 ascii 的名称,例如, 以避免遍历字符串。然而,有一半类似于这个问题的问题被问到了,因为有人有代表运算符的字符串并想要它们的函数。

回答by Manuel Richarz

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:

您可以使用该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));

回答by danniel

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

回答by Manu

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

我们可以使用 eval 来实现这一点,因为我们将它用于运算符检查。

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.

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

回答by Manu

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.

从我最近发布的另一个答案来看,这是在 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);

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.

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

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"; }

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

回答by cellcortex

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

您不能在 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*/ }