2011-01-15 35 views
26

是否可以在JavaScript中的類型實例之間定義自定義運算符?我可以在JavaScript中定義自定義運算符重載嗎?

例如,假設我有一個自定義的矢量類,是有可能使用

vect1 == vect2 

檢查平等,而底層代碼會是這樣呢?

operator ==(a, b) { 
    return a.x == b.x && a.y == b.y && a.z == b.z; 
} 

(這當然是無稽之談。)

回答

9

我同意,在矢量原型同等功能是最好的解決方案。請注意,您也可以通過鏈接構建其他類似中綴的操作符。

function Vector(x, y, z) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
} 

Vector.prototype.add = function (v2) { 
    var v = new Vector(this.x + v2.x, 
         this.y + v2.y, 
         this.z + v2.z); 
    return v; 
} 

Vector.prototype.equal = function (v2) { 
    return this.x == v2.x && this.y == v2.y && this.z == v2.z; 
} 

你可以看到online sample here

更新:這是一個更廣泛的示例,用於創建支持鏈接的Factory function

+1

我最近發現使用JQuery進行鏈接,它在某些情況下非常有用,非常感謝您的示例! – pimvdb

8

不,JavaScript不支持運算符重載。您將需要編寫一個做到這一點的方法:

Vector.prototype.equalTo = function(other) { 
    if (!(other instanceof Vector)) return false; 
    return a.x == b.x && a.y == b.y && a.z == b.z; 
} 

然後你就可以使用該方法,如:

vect1.equalTo(vect2) 
+0

是的,我目前在原型中也有一個函數。但是,我習慣於使用==進行相等性檢查。但是,如果這是不可能的,那麼我會忘記它 – pimvdb

4

不,這不是規範的一部分(這並不意味着有AREN 't some hacks)。

+0

這很好找,但==運算符似乎不是'可破解的'。 – pimvdb

+3

我真的希望這個鏈接仍然有效 – jedmao

8

,如果你想堅持使用==操作,你能做的最好的:

function Vector(x, y, z) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
} 

Vector.prototype.toString = function() { 
    return this.x + ";" + this.y + ";" + this.z; 
}; 

var a = new Vector(1, 2, 3); 
var b = new Vector(1, 2, 3); 
var c = new Vector(4, 5, 6); 


alert(String(a) == b); // true 
alert(String(a) == c); // false 
alert(a == b + ""); // true again (no object wrapper but a bit more ugly) 
+0

這也是一種可能性,但說實話,有點醜陋。我想我會更好地使用平等功能。 – pimvdb

+0

這並不像你想象的那麼醜陋,因爲你可能已經在你的對象上有一個'toString'函數,以便於調試。但是,再次,我只是寫了這個答案,因爲你說你更喜歡'=='操作符。功能。使用你最喜歡的東西。乾杯! :) – galambalazs

+0

確實有一個toString函數,但對於平等檢查來說,執行v1.equalsTo(v2)要比記住你必須將它轉換爲一個String容易,因爲這不是通常的做法 - 非常感謝無論如何! – pimvdb

1

下面是一個簡單的仿真,其使用guard operator平等測試:

function operator(node) 
    { 
    // Abstract the guard operator 
    var guard = " && "; 
    // Abstract the return statement 
    var action = "return "; 
    // return a function which compares two vector arguments 
    return Function("a,b", action + "a.x" + node + "b.x" + guard + "a.y" + node + "b.y" + guard + "a.z" + node + "a.z"); 
    } 

//Pass equals to operator; pass vectors to returned Function 
var foo = operator("==")({"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3}); 
var bar = operator("==")({"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}); 

//Result 
console.log(["foo",foo,"bar",bar]); 

對於非嚴格模式函數數組指數(在15.4中定義)的參數指定的數據的屬性的對象,其數字名稱值小於相應函數對象的形式參數的數量,最初與函數的執行上下文中的相應參數綁定共享它們的值。這意味着改變屬性會改變參數綁定的相應值,反之亦然。如果這樣的屬性被刪除然後重新定義或者屬性被改變爲訪問者屬性,則該對應關係被破壞。對於嚴格模式函數,參數對象的屬性值只是傳遞給函數的參數的副本,並且屬性值和形式參數值之間不存在動態鏈接。

參考

0

這不是你問題的直接答案,但值得注意。

PaperScript是JavaScript的簡單擴展,它增加了對運算符重載到任何對象的支持。

它用於在HTML5畫布上製作矢量圖形。

它解析PaperScript給JavaScript腳本上的標籤類型=「文/ paperscript」:

<!DOCTYPE html> 
<html> 
<head> 
<!-- Load the Paper.js library --> 
<script type="text/javascript" src="js/paper.js"></script> 
<!-- Define inlined PaperScript associate it with myCanvas --> 
<script type="text/paperscript" canvas="myCanvas"> 
    // Define a point to start with 
    var point1 = new Point(10, 20); 

    // Create a second point that is 4 times the first one. 
    // This is the same as creating a new point with x and y 
    // of point1 multiplied by 4: 
    var point2 = point1 * 4; 
    console.log(point2); // { x: 40, y: 80 } 

    // Now we calculate the difference between the two. 
    var point3 = point2 - point1; 
    console.log(point3); // { x: 30, y: 60 } 

    // Create yet another point, with a numeric value added to point3: 
    var point4 = point3 + 30; 
    console.log(point4); // { x: 60, y: 90 } 

    // How about a third of that? 
    var point5 = point4/3; 
    console.log(point5); // { x: 20, y: 30 } 

    // Multiplying two points with each other multiplies each 
    // coordinate seperately 
    var point6 = point5 * new Point(3, 2); 
    console.log(point6); // { x: 60, y: 60 } 

    var point7 = new Point(10, 20); 
    var point8 = point7 + { x: 100, y: 100 }; 
    console.log(point8); // { x: 110, y: 120 } 

    // Adding size objects to points work too, 
    // forcing them to be converted to a point first 
    var point9 = point8 + new Size(50, 100); 
    console.log(point9); // { x: 160, y: 220 } 

    // And using the object notation for size works just as well: 
    var point10 = point9 + { width: 40, height: 80 }; 
    console.log(point10); // { x: 200, y: 300 } 

    // How about adding a point in array notation instead? 
    var point5 = point10 + [100, 0]; 
    console.log(point5); // { x: 300, y: 300 } 
</script> 
</head> 
<body> 
    <canvas id="myCanvas" resize></canvas> 
</body> 
</html> 
+0

我意識到這一點是一箇舊的答案 - 不知道這與OP的問題有什麼關係? – brandonscript

+0

雖然這可能是有用的知識,但這實際上並沒有回答這個問題。 –

3

您可以更改JavaScript對象內置的方法,如valueOf()方法。對於任何兩個對象應用以下運算符>, <, <=, >=, -, + JavaScript會獲取每個對象的屬性valueOf(),因此它處理的運算符類似於:obj1.valueOf() == obj2.valueOf()(這在幕後)。您可以根據您的需要覆蓋valueOf()方法。舉例來說:

var Person = function(age, name){ 
    this.age = age; 
    this.name = name; 
} 

Person.prototype.valueOf(){ 
    return this.age; 
} 

var p1 = new Person(20, "Bob"), 
    p2 = new Person(30, "Bony"); 

console.log(p1 > p2); //false 
console.log(p1 < p2); //true 
console.log(p2 - p1); //10 
console.log(p2 + p1); //40 

//for == you should the following 
console.log(p2 >= p1 && p2 <= p1); // false 

所以這不是你的問題的確切答案,但我認爲這可能是對這類問題有用的東西。

相關問題