변수 연산자가 가능합니까?


89

다음 중 하나와 유사한 작업을 수행 할 수있는 방법이 있습니까?

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

답변:


174

상자에서 꺼내지 마십시오. 그러나 JS를 포함한 많은 언어로 손으로 빌드하는 것은 쉽습니다.

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

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

plus필요하지 않은 경우 문자열을 통과하지 않도록, 같은 ASCII 기반 이름을 사용할 수 있습니다 . 그러나 이와 유사한 질문의 절반은 누군가가 연산자를 나타내는 문자열을 가지고 있고 그들로부터 함수를 원했기 때문에 질문되었습니다.


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 값은 get 끝에서 단일 숫자로 변환 될 수 있으며 수신자 끝은이를 복잡한 구성 요소로 다시 간단히 변환 할 수 있습니다. 또는 더 복잡한 데이터의 경우 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.