54

有沒有辦法做類似下面的任東西:可變操作符是否可能?

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 

回答

104

不開箱即用。但是,用包括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

可以使用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)); 
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*/ } 
5

我相信你想要一個可變的操作符。這裏是一個,創建爲對象。你可以通過改變改變當前的操作:

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

在這一點上,你擁有所有的輸入和操作,剩下的部分是操作的結果。操作的接收者將得到一個原始值,字符串或數字,並且您無法防止這種情況。如果它不是一個任意的接收者,說一個你運算符超載的類的實例,你可以處理各種獲取/設置陷阱來攔截傳入值/防止覆蓋。您可以在某些中央查找中存儲操作數和操作,並使用一種簡單的方法將原始值追溯回產生它的操作,然後創建任何您想要執行自定義操作的邏輯。另一種方法可以允許任意的接收方在以後可以重構爲複雜的形式,將數據編碼爲原始值,以便它可以被逆轉回複雜的類。比如說,3個不同的8位整數(255,255,255)的RGB值可以轉換爲get端的單個數字,接收端可以簡單地將其轉換回其複雜的組件。或者對於更復雜的數據,你甚至可以返回一個JSON序列化的字符串。

通過訪問Harmony Proxies(帶有標誌的Firefox6 +,Nodejs),可以使整個過程變得非常容易,因爲您可以在基本上所有內容上創建陷印代理並從端到端反思整個過程,並執行任何您想要的操作。數據/類,調用valueOf /的toString /每一個可能的值的發動機內部可以訪問的干將,在with(trappingProxy){ "all variable lookup, creation, and setting in here invokes traps on our proxy"; }

2

的情況下,你已經預先認識任何接收機的對象,甚至是陷阱任意接收器的操作情況下,我們可以使用eval實現這一點,因爲我們正在使用它來進行操作員檢查。

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

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

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

這樣我們就可以使用動態算子評估。

相關問題