Os operadores de variáveis ​​são possíveis?


90

Existe uma maneira de fazer algo semelhante a uma das seguintes opções:

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

- OU -

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

Respostas:


177

Não fora da caixa. No entanto, é fácil de construir manualmente em muitas linguagens, incluindo JS.

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

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

Você pode usar nomes baseados em ASCII como plus, para evitar passar por strings se não precisar. No entanto, metade das perguntas semelhantes a esta foram feitas porque alguém tinha strings que representam os operadores e queria funções deles.


6

Eu acredito que você quer um operador variável. aqui está um, criado como objeto. você pode alterar a operação atual alterando:

[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

6

Você pode usar a eval()função, mas isso não é uma boa ideia. Acho que a melhor maneira é escrever funções para seus operadores como esta:

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

6

podemos implementar isso usando eval, já que o estamos usando para verificação de operador.

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

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

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

desta forma, podemos usar a avaliação dinâmica do operador.


3

De outra resposta que postei recentemente, isso está no V8 e acho que JavaScriptCore, mas não no Firefox e não é especificação. Como você pode interceptar a operação e os comparadores, pode implementar a sobrecarga nativa do operador na maioria das situações com um pouco de trabalho.

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

Resultado:

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

Neste ponto, você tem todas as entradas e a operação, então a parte restante é o resultado da operação. O receptor da operação obterá um valor primitivo, string ou número, e você não pode evitar isso. Se não for um receptor arbitrário, digamos uma instância da classe que você sobrecarregou de operador, você pode manipular várias armadilhas get / set para interceptar o valor de entrada / impedir a substituição. Você pode armazenar os operandos e a operação em alguma pesquisa central e usar um método simples para rastrear um valor primitivo de volta à operação que o produziu e, em seguida, criar qualquer lógica que desejar para fazer sua operação personalizada. Outro método que permitiria receptores arbitrários que mais tarde poderiam ser reconstituídos em formas complexas seria codificar os dados no valor primitivo para que possam ser revertidos de volta em sua classe complexa. Como, digamos, um valor RGB de 3 inteiros de 8 bits distintos (255,255,255) poderia ser convertido em um único número na extremidade de obtenção e a extremidade do receptor poderia facilmente convertê-lo de volta em seus componentes complexos. Ou, para dados mais complexos, você pode até retornar uma string JSON serializada.

Ter acesso aos Harmony Proxies (Firefox6 +, Nodejs com flag) torna todo esse processo imensamente mais fácil, já que você pode criar trapping proxies em basicamente tudo e fazer uma introspecção em todo o processo de ponta a ponta e fazer o que quiser. As instâncias de operando de seus dados / classe, os valueOf / toString / getters de todos os valores possíveis que o mecanismo interno pode acessar, qualquer objeto receptor que você tenha pré-conhecimento e até mesmo interceptar receptores arbitrários no caso dewith(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }


2

Você não pode sobrecarregar operadores em JavaScript. Você pode usar funções para ajudar

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*/ }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.