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


回答:


174

箱から出していない。ただし、JSを含む多くの言語で手作業で作成するのは簡単です。

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

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

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


6

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

[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

この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

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

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

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

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

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


3

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


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*/ }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.