ตัวดำเนินการตัวแปรเป็นไปได้หรือไม่?


90

มีวิธีทำสิ่งที่คล้ายกับวิธีใดวิธีหนึ่งต่อไปนี้:

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

คำตอบ:


177

ไม่ออกนอกกรอบ. อย่างไรก็ตามมันง่ายที่จะสร้างด้วยมือในหลายภาษารวมถึง JS

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

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

คุณสามารถใช้ชื่อที่ใช้ ascii เช่นplusเพื่อหลีกเลี่ยงการใช้สตริงหากคุณไม่ต้องการ อย่างไรก็ตามครึ่งหนึ่งของคำถามที่คล้ายกับคำถามนี้ถูกถามเนื่องจากมีคนมีสตริงที่เป็นตัวแทนของตัวดำเนินการและต้องการฟังก์ชันจากคำถามเหล่านี้


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

ณ จุดนี้คุณมีอินพุตและการดำเนินการทั้งหมดดังนั้นส่วนที่เหลือจึงเป็นผลลัพธ์ของการดำเนินการ ผู้รับของการดำเนินการจะได้รับค่าดั้งเดิมไม่ว่าจะเป็นสตริงหรือตัวเลขและคุณไม่สามารถป้องกันสิ่งนี้ได้ หากไม่ใช่ผู้รับตามอำเภอใจให้พูดว่าอินสแตนซ์ของคลาสที่คุณดำเนินการมากเกินไปคุณสามารถจัดการกับดักรับ / ตั้งค่าต่างๆเพื่อสกัดกั้นค่าที่เข้ามา / ป้องกันการเขียนทับ คุณสามารถจัดเก็บตัวถูกดำเนินการและการดำเนินการในการค้นหาส่วนกลางและใช้วิธีง่ายๆในการติดตามค่าดั้งเดิมกลับไปยังการดำเนินการที่สร้างขึ้นจากนั้นสร้างตรรกะใด ๆ ที่คุณต้องการดำเนินการแบบกำหนดเองของคุณ อีกวิธีหนึ่งที่อนุญาตให้ผู้รับตามอำเภอใจซึ่งสามารถสร้างขึ้นใหม่ในรูปแบบที่ซับซ้อนได้ในภายหลังก็คือการเข้ารหัสข้อมูลให้เป็นค่าดั้งเดิมเพื่อให้สามารถย้อนกลับไปยังคลาสที่ซับซ้อนของคุณได้ เช่นเดียวกับที่กล่าวว่าค่า RGB ของจำนวนเต็ม 8 บิตที่แตกต่างกัน 3 ตัว (255,255,255) สามารถแปลงเป็นตัวเลขเดียวที่จุดรับและจุดสิ้นสุดของตัวรับสัญญาณสามารถแปลงกลับเป็นส่วนประกอบที่ซับซ้อนได้เล็กน้อย หรือสำหรับข้อมูลที่ซับซ้อนมากขึ้นคุณสามารถส่งคืนสตริงอนุกรม JSON ได้

การเข้าถึง Harmony Proxies (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.