Apakah Operator Variabel Dimungkinkan?

90

Adakah cara untuk melakukan sesuatu yang mirip dengan salah satu dari berikut ini:

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

-- ATAU --

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

Jawaban:

177

Tidak di luar kotak. Namun, mudah untuk membuatnya dengan tangan dalam banyak bahasa termasuk JS.

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

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

Anda dapat menggunakan nama berbasis ascii seperti plus, untuk menghindari melalui string jika Anda tidak perlu. Namun, setengah dari pertanyaan yang serupa dengan pertanyaan ini ditanyakan karena seseorang memiliki string yang mewakili operator dan menginginkan fungsi darinya.


sumber
6

Saya yakin Anda menginginkan operator variabel. inilah satu, dibuat sebagai objek. Anda dapat mengubah operasi saat ini dengan mengubah:

[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
danniel
sumber
6

Anda dapat menggunakan eval()fungsi tersebut, tetapi itu bukan ide yang bagus. Saya pikir cara yang lebih baik adalah menulis fungsi untuk operator Anda seperti ini:

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));
Manuel Richarz
sumber
6

kita dapat mengimplementasikan ini menggunakan eval, karena kita menggunakannya untuk pemeriksaan operator.

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

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

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

dengan cara ini kita dapat menggunakan evaluasi operator dinamis.

Manu
sumber
3

Dari jawaban lain yang baru saya posting, ini ada di V8 dan saya pikir JavaScriptCore, tetapi bukan Firefox dan itu bukan spesifikasi. Karena Anda dapat menangkap operasi dan pembanding, Anda dapat mengimplementasikan overloading bawaan operator dalam banyak situasi dengan sedikit usaha.

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

Keluaran:

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

Pada titik ini Anda memiliki semua input dan operasi sehingga bagian yang tersisa adalah hasil dari operasi tersebut. Penerima operasi akan mendapatkan nilai primitif, baik string atau angka, dan Anda tidak dapat mencegahnya. Jika ini bukan penerima arbitrer, katakanlah sebuah instance dari kelas yang telah Anda overload oleh operator, Anda dapat menangani berbagai get / set traps untuk mencegat nilai yang masuk / mencegah penimpaan. Anda dapat menyimpan operand dan operasi di beberapa pencarian pusat dan menggunakan metode sederhana untuk melacak kembali nilai primitif ke operasi yang memproduksinya, lalu membuat logika apa pun yang Anda inginkan untuk melakukan operasi kustom. Metode lain yang memungkinkan penerima arbitrer yang nantinya dapat disusun kembali menjadi bentuk kompleks adalah dengan menyandikan data ke dalam nilai primitif sehingga dapat dikembalikan ke kelas kompleks Anda. Seperti katakanlah nilai RGB dari 3 bilangan bulat 8bit berbeda (255.255.255) dapat diubah menjadi satu nomor di ujung get dan ujung penerima dapat dengan mudah mengubahnya kembali menjadi komponen kompleksnya. Atau untuk data yang lebih kompleks, Anda bahkan dapat mengembalikan string serial JSON.

Memiliki akses ke Harmony Proxies (Firefox6 +, Nodejs with flag) membuat seluruh proses ini sangat mudah, karena Anda dapat membuat proxy yang menjebak pada dasarnya semua dan introspeksi seluruh proses dari ujung ke ujung dan melakukan apa pun yang Anda inginkan. Instance operan data / kelas Anda, valueOf / toString / getter dari setiap kemungkinan nilai yang dapat diakses mesin internal, objek penerima apa pun yang Anda ketahui sebelumnya, dan bahkan menjebak penerima arbitrer dalam kasuswith(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }


sumber
2

Anda tidak dapat membebani operator di JavaScript. Anda tentu saja dapat menggunakan fungsi untuk membantu

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*/ }
cellcortex
sumber