93 votes

Des opérateurs variables sont-ils possibles?

Existe-t-il un moyen de faire quelque chose de similaire à l’un des suivants:

 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
 

192voto

delnan Points 52260

Pas hors de la boîte. Cependant, il est facile de construire à la main dans de nombreuses langues, y compris JS.

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

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

Vous pouvez utiliser des noms basés sur ASCII, tels que plus , pour éviter de passer par des chaînes si vous n'en avez pas besoin. Cependant, la moitié des questions similaires à celle-ci ont été posées parce que quelqu'un avait des chaînes représentant des opérateurs et souhaitait des fonctions de leur part.

8voto

danniel Points 505

Je crois que vous voulez un opérateur variable. en voici un, créé en tant qu'objet. vous pouvez modifier l'opération en cours en modifiant:

 [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
 

6voto

Manuel Richarz Points 957

Vous pouvez utiliser la fonction eval() , mais ce n'est pas une bonne idée. Je pense que le meilleur moyen est d'écrire des fonctions pour vos opérateurs comme ceci:

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

3voto

benvie Points 6181

À partir d'une autre réponse que j'ai publié récemment, c'est en V8 et je pense que JavaScriptCore, mais pas Firefox et il n'est pas spec. Puisque vous pouvez recouvrir le fonctionnement et les comparateurs vous pouvez implémenter l'opérateur natif de surcharge dans la plupart des situations avec un peu de travail.

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

Sortie:

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

À ce stade, vous avez toutes les entrées et les opérations de la partie restante est le résultat de l'opération. Le récepteur de l'opération d'obtenir une valeur primitive, une chaîne ou un nombre, et vous ne pouvez pas l'en empêcher. Si elle n'est pas arbitraire, récepteur dire une instance de la classe que vous avez opérateur surchargé, vous pouvez gérer les différentes get/set pièges à interception de la valeur entrante/éviter d'écraser. Vous pouvez stocker les opérandes et le fonctionnement dans certains central de la recherche et de l'utilisation d'une méthode simple pour trouver la trace d'une primitive de la valeur de retour de l'opération qui l'a produite, et ensuite de créer le logique que vous voulez faire de votre opération personnalisée. Une autre méthode qui permettrait à l'arbitraire des récepteurs qui pourrait plus tard être reconstitué dans des formes complexes serait dans l'encodage des données dans la valeur primitive de sorte qu'il peut être renversée en arrière dans votre classe complexe. Comme, disons, une valeur RVB de 3 8bit entiers (255,255,255) pourrait être converti en un numéro unique sur le fin et le récepteur pourrait trivial reconvertir en ses composants complexes. Ou pour les plus complexes de données, vous pourriez même le retour JSON chaîne sérialisée.

Avoir accès à l'Harmonie des Procurations (Firefox6+, Nodejs avec drapeau) rend l'ensemble de ce processus extrêmement facile, comme vous pouvez le créer de piégeage des procurations sur pratiquement tout et de connaître le fonctionnement de l'ensemble du processus du début à la fin et faire ce que vous voulez. L'opérande instances de vos données/la classe, le valueOf/toString/getters de chaque valeur possible du moteur interne d'accès, de n'importe quel récepteur de l'objet que vous avez pré-conscience de, et de même piège arbitraire des récepteurs dans le cas d' with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }

2voto

cellcortex Points 1894

Vous ne pouvez pas surcharger les opérateurs en JavaScript. Vous pouvez bien sûr utiliser des fonctions pour vous aider

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X