Các toán tử biến có khả thi không?


89

Có cách nào để làm điều gì đó tương tự như một trong hai cách sau:

var1 = 10; var2 = 20;
var operator = "<";
console.log(var1 operator var2); // returns true

-- HOẶC LÀ --

var1 = 10; var2 = 20;
var operator = "+";
total = var1 operator var2; // total === 30

Câu trả lời:


174

Không ra khỏi hộp. Tuy nhiên, thật dễ dàng để xây dựng thủ công bằng nhiều ngôn ngữ bao gồm cả JS.

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

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

Bạn có thể sử dụng các tên dựa trên ascii như plus, để tránh đi qua các chuỗi nếu bạn không cần thiết. Tuy nhiên, một nửa số câu hỏi tương tự như câu hỏi này được hỏi vì ai đó có các chuỗi đại diện cho các toán tử và muốn các hàm từ chúng.


6

Tôi tin rằng bạn muốn một toán tử biến. đây là một, được tạo dưới dạng đối tượng. bạn có thể thay đổi hoạt động hiện tại bằng cách thay đổi:

[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

Bạn có thể sử dụng eval()hàm, nhưng đó không phải là một ý kiến ​​hay. Tôi nghĩ cách tốt hơn là viết các hàm cho các toán tử của bạn như sau:

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

chúng ta có thể thực hiện điều này bằng eval, vì chúng ta đang sử dụng nó để kiểm tra toán tử.

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

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

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

theo cách này, chúng ta có thể sử dụng đánh giá toán tử động.


3

Từ một câu trả lời khác mà tôi đã đăng gần đây, đây là trong V8 và tôi nghĩ JavaScriptCore, nhưng không phải Firefox và nó không phải là thông số kỹ thuật. Vì bạn có thể bẫy hoạt động và bộ so sánh, bạn có thể thực hiện nạp chồng toán tử gốc trong hầu hết các tình huống với một chút công việc.

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);

Đầu ra:

[ { 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 } ]

Tại thời điểm này, bạn có tất cả các đầu vào và hoạt động nên phần còn lại là kết quả của hoạt động. Người nhận của hoạt động sẽ nhận được một giá trị nguyên thủy, là chuỗi hoặc số và bạn không thể ngăn điều này. Nếu đó không phải là bộ nhận tùy ý, giả sử một phiên bản của lớp mà bạn đã nạp chồng toán tử, bạn có thể xử lý các bẫy nhận / đặt khác nhau để chặn giá trị đến / ngăn ghi đè. Bạn có thể lưu trữ các toán hạng và hoạt động trong một số tra cứu trung tâm và sử dụng một phương pháp đơn giản để theo dõi một giá trị nguyên thủy trở lại hoạt động tạo ra nó, sau đó tạo bất kỳ logic nào bạn muốn để thực hiện hoạt động tùy chỉnh của mình. Một phương pháp khác sẽ cho phép các máy thu tùy ý mà sau này có thể được hoàn nguyên thành các dạng phức hợp là mã hóa dữ liệu thành giá trị nguyên thủy để nó có thể được đảo ngược trở lại lớp phức hợp của bạn. Giống như nói một giá trị RGB của 3 số nguyên 8bit riêng biệt (255,255,255) có thể được chuyển đổi thành một số duy nhất ở đầu nhận và đầu nhận có thể chuyển đổi nó trở lại thành các thành phần phức tạp. Hoặc đối với dữ liệu phức tạp hơn, bạn thậm chí có thể trả về một chuỗi được tuần tự hóa JSON.

Việc có quyền truy cập vào Harmony Proxy (Firefox6 +, Nodejs with flag) làm cho toàn bộ quá trình này trở nên dễ dàng hơn nhiều, vì bạn có thể tạo các proxy bẫy về cơ bản mọi thứ và xem xét toàn bộ quá trình từ đầu đến cuối và làm bất cứ điều gì bạn muốn. Các thể hiện toán hạng của dữ liệu / lớp của bạn, giá trị valueOf / toString / getters của mọi giá trị có thể mà bộ máy bên trong có thể truy cập, bất kỳ đối tượng người nhận nào bạn đã biết trước và thậm chí bẫy người nhận tùy ý trong trường hợpwith(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }


2

Bạn không thể quá tải các toán tử trong JavaScript. Tất nhiên bạn có thể sử dụng các chức năng để trợ giúp

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*/ }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.