97

次のいずれかに似た方法はありますか?

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

- また -

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

7 に答える 7

200

箱から出してはいけません。ただし、JS を含む多くの言語で手動で簡単に作成できます。

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

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

のような ASCII ベースの名前を使用plusして、必要がない場合は文字列を通過しないようにすることができます。ただし、これと同様の質問の半分は、演算子を表す文字列があり、それらの関数を求めていたために尋ねられました。

于 2011-04-29T16:04:27.930 に答える
9

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

[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
于 2011-04-29T16:11:29.387 に答える
7

関数を使用できます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));
于 2011-04-29T16:01:28.827 に答える
2

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*/ }
于 2011-04-29T16:01:31.270 に答える
2

最近投稿した別の回答から、これは 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) にアクセスできると、基本的にすべてのトラッピング プロキシを作成し、プロセス全体をエンドツーエンドで内省し、必要なことを何でも実行できるため、このプロセス全体が非常に簡単になります。データ/クラスのオペランド インスタンス、内部エンジンがアクセスできる可能性のあるすべての値の valueOf/toString/getters、事前に認識しているレシーバー オブジェクト、場合によっては任意のレシーバーをトラップすることさえできます。with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }

于 2011-11-10T09:48:01.560 に答える