Есть ли способ сделать что-то похожее на одно из следующих:
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
Есть ли способ сделать что-то похожее на одно из следующих:
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
Не из коробки. Однако его легко создавать вручную на многих языках, включая JS.
var operators = {
'+': function(a, b) { return a + b },
'<': function(a, b) { return a < b },
// ...
};
var op = '+';
alert(operators[op](10, 20));
Вы можете использовать имена на основе ascii, такие как plus
, чтобы избежать прохождения строк, если вам это не нужно. Тем не менее, половина вопросов, подобных этому, были заданы, потому что у кого-то были строки, представляющие операторы и требуемые функции от них.
Вы можете использовать функцию 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));
Я считаю, что вам нужен оператор переменной. здесь один, созданный как объект. вы можете изменить текущую операцию, изменив:
[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
Из другого ответа, который я недавно опубликовал, это в 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 для перехвата входящего значения/предотвращения перезаписи. Вы можете хранить операнды и операции в некотором центральном поиске и использовать простой метод для отслеживания примитивного значения обратно к операции, которая его создала, а затем создать любую логику, которую вы хотите выполнить свою собственную операцию. Другой метод, который позволил бы произвольным приемникам, которые впоследствии могли быть перестроены в сложные формы, заключался бы в кодировании данных в примитивное значение, чтобы его можно было отменить обратно в ваш сложный класс. Например, значение RGB из 3 различных 8-битных целых чисел (255,255,255) может быть преобразовано в одно число на конце завершения, а конец приемника может тривиально преобразовать его обратно в его сложные компоненты. Или для более сложных данных вы можете даже вернуть сериализованную строку JSON.
Доступ к средствам Harmony Proxies (Firefox6 +, Nodejs с флагом) упрощает весь этот процесс, так как вы можете создавать прокси-серверы в основном для всего и анализировать весь процесс из конца в конец и делать все, что хотите. Экземпляры операнда ваших данных/класса, значениеOf/toString/getters любого возможного значения, к которому может обращаться внутренний движок, любой объект-получатель, у вас есть предварительное понимание и даже захват произвольных приемников в случае 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*/ }
мы можем реализовать это с помощью eval, поскольку мы используем его для проверки оператора.
var number1 = 30;
var number2 = 40;
var operator = "===";
function evaluate(param1, param2, operator) {
return eval(param1 + operator + param2);
}
if(evaluate(number1, number2, operator)) {
}
таким образом мы можем использовать динамическую оценку оператора.