¿Son posibles los operadores variables?

Respuestas:

174

No fuera de la caja. Sin embargo, es fácil de construir a mano en muchos lenguajes, incluido JS.

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

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

Puede usar nombres basados ​​en ascii como plus, para evitar pasar por cadenas si no es necesario. Sin embargo, la mitad de las preguntas similares a esta se hicieron porque alguien tenía cadenas que representaban operadores y quería funciones de ellos.


fuente
6

Creo que quieres un operador variable. aquí hay uno, creado como objeto. puede cambiar la operación actual cambiando:

[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
danniel
fuente
6

Puede utilizar la eval()función, pero no es una buena idea. Creo que la mejor manera es escribir funciones para sus operadores de esta manera:

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));
Manuel Richarz
fuente
6

podemos implementar esto usando eval, ya que lo estamos usando para la verificación del operador.

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

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

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

de esta forma podemos utilizar la evaluación dinámica de operadores.

Manu
fuente
3

De otra respuesta que publiqué recientemente, esto está en V8 y creo que JavaScriptCore, pero no Firefox y no es una especificación. Dado que puede capturar la operación y los comparadores, puede implementar la sobrecarga nativa del operador en la mayoría de las situaciones con un poco de trabajo.

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

Salida:

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

En este punto tiene todas las entradas y la operación, por lo que la parte restante es el resultado de la operación. El receptor de la operación obtendrá un valor primitivo, ya sea una cadena o un número, y no puede evitarlo. Si no es un receptor arbitrario, digamos una instancia de la clase que sobrecargó el operador, puede manejar varias trampas get / set para interceptar el valor entrante / evitar la sobrescritura. Puede almacenar los operandos y la operación en alguna búsqueda central y usar un método simple para rastrear un valor primitivo hasta la operación que lo produjo, y luego crear la lógica que desee para hacer su operación personalizada. Otro método que permitiría receptores arbitrarios que luego podrían reconstituirse en formas complejas sería codificar los datos en el valor primitivo para que puedan invertirse nuevamente en su clase compleja. Por ejemplo, un valor RGB de 3 enteros distintos de 8 bits (255,255,255) podría convertirse en un solo número en el extremo de obtención y el extremo del receptor podría convertirlo de nuevo en sus componentes complejos. O para datos más complejos, incluso podría devolver una cadena serializada JSON.

Tener acceso a Harmony Proxies (Firefox6 +, Nodejs con bandera) hace que todo este proceso sea inmensamente más fácil, ya que puede crear proxies de captura en básicamente todo e introspectar todo el proceso de un extremo a otro y hacer lo que quiera. Las instancias de operando de sus datos / clase, el valueOf / toString / getters de cada valor posible al que el motor interno puede acceder, cualquier objeto receptor del que tenga conocimiento previo, e incluso atrapar receptores arbitrarios en el caso dewith(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }


fuente
2

No puede sobrecargar operadores en JavaScript. Por supuesto, puede utilizar funciones para ayudar

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*/ }
corteza celular
fuente