Are Variable Operators Possible?
有没有一种方法可以执行以下任一操作:
1 2 3 | var1 = 10; var2 = 20; var operator ="<"; console.log(var1 operator var2); // returns true |
- 要么 -
1 2 3 | var1 = 10; var2 = 20; var operator ="+"; total = var1 operator var2; // total === 30 |
并非开箱即用。但是,很容易以多种语言(包括JS)进行手工构建。
1 2 3 4 5 6 7 8 | var operators = { '+': function(a, b) { return a + b }, '<': function(a, b) { return a < b }, // ... }; var op = '+'; alert(operators[op](10, 20)); |
您可以使用诸如
我们可以使用eval来实现此功能,因为我们将其用于操作员检查。
1 2 3 4 5 6 7 8 9 10 | var number1 = 30; var number2 = 40; var operator ="==="; function evaluate(param1, param2, operator) { return eval(param1 + operator + param2); } if(evaluate(number1, number2, operator)) { } |
这样,我们可以使用动态算子评估。
我相信您想要一个变量运算符。这是一个作为对象创建的对象。您可以通过以下方式更改当前操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | [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 |
您可以使用
我认为更好的方法是像这样为您的操作员编写函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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)); |
从我最近发布的另一个答案来看,这是在V8中,我认为是JavaScriptCore,但不是Firefox,这不是规范。由于您可以捕获操作和比较器,因此您可以在大多数情况下通过一些工作来实现操作员本机重载。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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); |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | [ { 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 / getters,您事先知道的任何接收者对象,甚至在
您不能在JavaScript中重载运算符。您可以偏离路线使用功能来帮助
1 2 3 4 5 6 7 8 9 10 11 12 | 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*/ } |