54

有没有办法做类似下面的任东西:可变操作符是否可能?

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 

回答

104

不开箱即用。但是,用包括JS在内的多种语言手动构建起来很容易。

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

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

您可以使用基于ASCII的名称,如plus,以避免通过串去,如果你不需要。然而,有一半类似于这个问题的问题被问到,因为有人有代表操作员的字符串并想要他们的功能。

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

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

从另外一个答案,我最近公布,这是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 } ] 

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

通过访问Harmony Proxies(带有标志的Firefox6 +,Nodejs),可以使整个过程变得非常容易,因为您可以在基本上所有内容上创建陷印代理并从端到端反思整个过程,并执行任何您想要的操作。数据/类,调用valueOf /的toString /每一个可能的值的发动机内部可以访问的干将,在with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }

2

的情况下,你已经预先认识任何接收机的对象,甚至是陷阱任意接收器的操作情况下,我们可以使用eval实现这一点,因为我们正在使用它来进行操作员检查。

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

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

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

这样我们就可以使用动态算子评估。

相关问题