다음 중 하나와 유사한 작업을 수행 할 수있는 방법이 있습니까?
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));
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));
최근에 게시 한 다른 답변에서 이것은 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 값은 get 끝에서 단일 숫자로 변환 될 수 있으며 수신자 끝은이를 복잡한 구성 요소로 다시 간단히 변환 할 수 있습니다. 또는 더 복잡한 데이터의 경우 JSON 직렬화 된 문자열을 반환 할 수도 있습니다.
Harmony 프록시 (Firefox6 +, 플래그가있는 Nodejs)에 액세스하면 기본적으로 모든 것에 트 랩핑 프록시를 만들고 전체 프로세스를 처음부터 끝까지 조사하고 원하는대로 수행 할 수 있으므로 전체 프로세스가 매우 쉬워집니다. 데이터 / 클래스의 피연산자 인스턴스, 내부 엔진이 액세스 할 수있는 모든 가능한 값의 valueOf / toString / getters, 사전 인식이있는 모든 수신자 객체, 심지어 다음과 같은 경우 임의의 수신자를 트랩합니다.with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }