次のいずれかに類似した方法を実行する方法はありますか?
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
箱から出していない。ただし、JSを含む多くの言語で手作業で簡単にビルドできます。
var operators = {
'+': function(a, b) { return a + b },
'<': function(a, b) { return a < b },
// ...
};
var op = '+';
alert(operators[op](10, 20));
plus
のようなASCIIベースの名前を使用して、必要がない場合に文字列を調べないようにすることができます。しかし、誰かが演算子を表す文字列を持っていて、そこから関数を求めていたため、これに似た質問の半分が尋ねられました。
変数演算子が必要だと思います。これがオブジェクトとして作成されたものです。以下を変更することにより、現在の操作を変更できます。
[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
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));
演算子チェックに使用しているため、evalを使用してこれを実装できます。
var number1 = 30;
var number2 = 40;
var operator = "===";
function evaluate(param1, param2, operator) {
return eval(param1 + operator + param2);
}
if(evaluate(number1, number2, operator)) {
}
このようにして、動的な演算子評価を使用できます。
私が最近投稿した別の回答から、これは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"; }
の場合は任意のレシーバーもトラップします
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*/ }