web-dev-qa-db-ja.com

変数演算子は可能ですか?

次のいずれかに類似した方法を実行する方法はありますか?

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

-OR-

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

箱から出していない。ただし、JSを含む多くの言語で手作業で簡単にビルドできます。

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

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

plusのようなASCIIベースの名前を使用して、必要がない場合に文字列を調べないようにすることができます。しかし、誰かが演算子を表す文字列を持っていて、そこから関数を求めていたため、これに似た質問の半分が尋ねられました。

148
user395760

変数演算子が必要だと思います。これがオブジェクトとして作成されたものです。以下を変更することにより、現在の操作を変更できます。

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

eval()関数を使用できますが、それはお勧めできません。より良い方法は、次のような演算子の関数を書くことだと思います。

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
Manuel Richarz

演算子チェックに使用しているため、evalを使用してこれを実装できます。

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

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

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

このようにして、動的な演算子評価を使用できます。

5
Manu

私が最近投稿した別の回答から、これはV8にあり、JavaScriptCoreだと思いますが、Firefoxではなく、仕様ではありません。操作とコンパレーターをトラップできるので、少しの作業でほとんどの状況で演算子ネイティブのオーバーロードを実装できます。

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

出力:

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

この時点で、すべての入力と操作があるので、残りの部分は操作の結果です。操作の受信者は、文字列または数値のプリミティブ値を取得しますが、これを防ぐことはできません。オペレーターがオーバーロードしたクラスのインスタンスなど、任意の受信者ではない場合、さまざまなget/setトラップを処理して、着信値をインターセプトしたり、上書きを防止したりできます。オペランドと演算をいくつかの中央ルックアップに格納し、単純な方法を使用してプリミティブ値を生成した演算までトレースし、カスタム演算を実行するロジックを作成できます。後で複雑な形式に再構成できる任意のレシーバーを許可する別の方法は、データをプリミティブ値にエンコードして、複雑なクラスに戻すことができるようにすることです。たとえば、3つの異なる8ビット整数(255,255,255)のRGB値を取得側で単一の数値に変換し、受信側でそれを単純な変換して複雑なコンポーネントに戻すことができます。または、より複雑なデータの場合は、JSONシリアル化された文字列を返すこともできます。

Harmony Proxies(Firefox6 +、Nodejs with flag)にアクセスすると、このプロセス全体が非常に簡単になります。基本的にすべてのトラッププロキシを作成し、プロセス全体をエンドツーエンドで調べて、必要な処理を実行できます。データ/クラスのオペランドインスタンス、内部エンジンがアクセスする可能性のあるすべての値のvalueOf/toString/getter、事前に認識しているレシーバーオブジェクト、with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }の場合は任意のレシーバーもトラップします

3
user748221

JavaScriptで演算子をオーバーロードすることはできません。もちろん、関数を使用して支援することができます

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