变量运算符可以吗?

发布于 2024-11-04 10:05:29 字数 276 浏览 6 评论 0原文

有没有办法执行类似于以下任一操作的操作:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

笔芯 2024-11-11 10:05:29

不是开箱即用的。然而,用包括 JS 在内的许多语言手动构建都很容易。

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

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

您可以使用基于 ascii 的名称,例如 plus,以避免在不需要时遍历字符串。然而,有一半与此类似的问题被问到,因为有人拥有代表运算符的字符串并希望从中获得函数。

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.

行雁书 2024-11-11 10:05:29

我们可以使用 eval 来实现这一点,因为我们用它来进行操作员检查。

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

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

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

这样我们就可以使用动态算子求值。

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.

情魔剑神 2024-11-11 10:05:29

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

[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

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
命比纸薄 2024-11-11 10:05:29

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

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));
活雷疯 2024-11-11 10:05:29

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

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)

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)

左岸枫 2024-11-11 10:05:29

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

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*/ }
平安喜乐 2024-11-11 10:05:29

从我最近发布的另一个答案来看,这是在 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 值可以在获取端转换为单个数字,而接收端可以轻松地将其转换回其复杂组件。或者,对于更复杂的数据,您甚至可以返回 JSON 序列化字符串。

访问 Harmony 代理(Firefox6+、带标志的 Nodejs)使整个过程变得非常容易,因为您可以在基本上所有内容上创建捕获代理,并从头到尾反思整个过程并做任何您想做的事情。数据/类的操作数实例、内部引擎可能访问的每个可能值的 valueOf/toString/getters、您预先了解的任何接收器对象,甚至在 with(traappingProxy 的情况下捕获任意接收器){ “这里的所有变量查找、创建和设置都会调用我们代理上的陷阱”; }

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

不念旧人 2024-11-11 10:05:29

复制自 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";
},

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";
},
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文