Gli operatori variabili sono possibili?


90

C'è un modo per fare qualcosa di simile a uno dei seguenti:

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

-- O --

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

Risposte:


177

Non fuori dagli schemi. Tuttavia, è facile da costruire a mano in molte lingue, incluso JS.

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

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

Puoi usare nomi basati su ASCII come plus, per evitare di passare attraverso le stringhe se non è necessario. Tuttavia, metà delle domande simili a questa sono state poste perché qualcuno aveva stringhe che rappresentavano operatori e desiderava funzioni da loro.


6

Credo che tu voglia un operatore variabile. eccone uno, creato come oggetto. è possibile modificare l'operazione corrente modificando:

[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

Puoi usare la eval()funzione, ma non è una buona idea. Penso che il modo migliore sia scrivere funzioni per i tuoi operatori come questa:

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

possiamo implementarlo usando eval, dato che lo stiamo usando per il controllo dell'operatore.

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

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

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

in questo modo possiamo utilizzare la valutazione dinamica dell'operatore.


3

Da un'altra risposta che ho pubblicato di recente, questo è in V8 e penso JavaScriptCore, ma non Firefox e non è specifica. Dato che è possibile intercettare l'operazione e i comparatori, è possibile implementare il sovraccarico nativo dell'operatore nella maggior parte delle situazioni con un po 'di lavoro.

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

Produzione:

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

A questo punto hai tutti gli input e l'operazione quindi la parte rimanente è il risultato dell'operazione. Il destinatario dell'operazione riceverà un valore primitivo, stringa o numero, e non puoi impedirlo. Se non è un ricevitore arbitrario, ad esempio un'istanza della classe che hai sovraccaricato dall'operatore, puoi gestire vari get / set trap per intercettare il valore in entrata / impedire la sovrascrittura. È possibile memorizzare gli operandi e l'operazione in una ricerca centrale e utilizzare un metodo semplice per ricondurre un valore primitivo all'operazione che lo ha prodotto, quindi creare la logica che si desidera per eseguire l'operazione personalizzata. Un altro metodo che consentirebbe ricevitori arbitrari che potrebbero essere successivamente ricostituiti in forme complesse sarebbe quello di codificare i dati nel valore primitivo in modo che possano essere invertiti nella tua classe complessa. Ad esempio, un valore RGB di 3 interi distinti a 8 bit (255,255,255) potrebbe essere convertito in un singolo numero all'estremità get e l'estremità del ricevitore potrebbe banalmente riconvertirlo nei suoi componenti complessi. Oppure, per dati più complessi, potresti persino restituire una stringa serializzata JSON.

Avere accesso a Harmony Proxies (Firefox6 +, Nodejs con flag) rende l'intero processo immensamente più semplice, poiché puoi creare proxy di trapping praticamente su tutto e analizzare l'intero processo dall'inizio alla fine e fare quello che vuoi. Le istanze dell'operando dei tuoi dati / classe, il valore di / toString / getter di ogni possibile valore a cui il motore interno può accedere, qualsiasi oggetto ricevitore di cui hai consapevolezza e persino intercettare ricevitori arbitrari nel caso diwith(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }


2

Non puoi sovraccaricare gli operatori in JavaScript. Ovviamente puoi usare le funzioni per aiutare

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*/ }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.