Sind variable Operatoren möglich?

88

Gibt es eine Möglichkeit, etwas Ähnliches wie das Folgende zu tun:

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

-- ODER --

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

Antworten:

171

Nicht sofort einsatzbereit. Es ist jedoch einfach, in vielen Sprachen, einschließlich JS, von Hand zu erstellen.

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

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

Sie können ASCII-basierte Namen wie verwenden plus, um das Durchlaufen von Zeichenfolgen zu vermeiden, wenn Sie dies nicht benötigen. Die Hälfte der ähnlichen Fragen wurde jedoch gestellt, weil jemand Zeichenfolgen hatte, die Operatoren darstellen, und Funktionen von ihnen wollte.


quelle
6

Ich glaube, Sie wollen einen variablen Operator. Hier ist eine, die als Objekt erstellt wurde. Sie können den aktuellen Vorgang ändern, indem Sie Folgendes ändern:

[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
quelle
6

Sie können die eval()Funktion verwenden, aber das ist keine gute Idee. Ich denke, der bessere Weg ist, Funktionen für Ihre Bediener wie folgt zu schreiben:

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
quelle
6

Wir können dies mit eval implementieren, da wir es für die Operatorprüfung verwenden.

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

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

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

Auf diese Weise können wir die dynamische Operatorauswertung verwenden.

Manu
quelle
3

Aus einer anderen Antwort, die ich kürzlich gepostet habe, geht hervor, dass dies in V8 ist und ich denke, JavaScriptCore, aber nicht Firefox und es ist keine Spezifikation. Da Sie die Operation und die Komparatoren abfangen können, können Sie in den meisten Situationen mit ein wenig Arbeit eine native Überladung des Operators implementieren.

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

Ausgabe:

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

Zu diesem Zeitpunkt haben Sie alle Eingaben und die Operation, sodass der verbleibende Teil das Ergebnis der Operation ist. Der Empfänger der Operation erhält einen primitiven Wert, entweder eine Zeichenfolge oder eine Zahl, und Sie können dies nicht verhindern. Wenn es sich nicht um einen willkürlichen Empfänger handelt, z. B. um eine Instanz der Klasse, die Ihr Operator überladen hat, können Sie verschiedene get / set-Traps verarbeiten, um den eingehenden Wert abzufangen / ein Überschreiben zu verhindern. Sie können die Operanden und Operationen in einer zentralen Suche speichern und mithilfe einer einfachen Methode einen primitiven Wert auf die Operation zurückführen, die ihn erzeugt hat, und dann die Logik erstellen, die Sie für Ihre benutzerdefinierte Operation ausführen möchten. Eine andere Methode, die beliebige Empfänger ermöglicht, die später in komplexe Formen rekonstituiert werden könnten, besteht darin, die Daten in den primitiven Wert zu codieren, damit sie wieder in Ihre komplexe Klasse umgewandelt werden können. Wie gesagt, ein RGB-Wert von 3 verschiedenen 8-Bit-Ganzzahlen (255,255,255) könnte am get-Ende in eine einzelne Zahl umgewandelt werden, und das Empfängerende könnte ihn trivial wieder in seine komplexen Komponenten umwandeln. Bei komplexeren Daten können Sie sogar eine serialisierte JSON-Zeichenfolge zurückgeben.

Der Zugriff auf Harmony Proxies (Firefox6 +, Nodejs mit Flag) erleichtert diesen gesamten Prozess erheblich, da Sie Trapping-Proxys für praktisch alles erstellen und den gesamten Prozess von Ende zu Ende überprüfen und tun können, was Sie wollen. Die Operandeninstanzen Ihrer Daten / Klasse, der Wert von / toString / Getter für jeden möglichen Wert, auf den die interne Engine zugreifen kann, jedes Empfängerobjekt, das Sie bereits kennen, und im Fall von sogar beliebige Empfänger abfangenwith(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }


quelle
2

Sie können Operatoren in JavaScript nicht überladen. Sie können natürlich Funktionen verwenden, um zu helfen

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*/ }
Zellkortex
quelle