是否可以在JavaScript中的類型實例之間定義自定義運算符?我可以在JavaScript中定義自定義運算符重載嗎?
例如,假設我有一個自定義的矢量類,是有可能使用
vect1 == vect2
檢查平等,而底層代碼會是這樣呢?
operator ==(a, b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
(這當然是無稽之談。)
是否可以在JavaScript中的類型實例之間定義自定義運算符?我可以在JavaScript中定義自定義運算符重載嗎?
例如,假設我有一個自定義的矢量類,是有可能使用
vect1 == vect2
檢查平等,而底層代碼會是這樣呢?
operator ==(a, b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
(這當然是無稽之談。)
我同意,在矢量原型同等功能是最好的解決方案。請注意,您也可以通過鏈接構建其他類似中綴的操作符。
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。
不,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)
是的,我目前在原型中也有一個函數。但是,我習慣於使用==進行相等性檢查。但是,如果這是不可能的,那麼我會忘記它 – pimvdb
不,這不是規範的一部分(這並不意味着有AREN 't some hacks)。
,如果你想堅持使用==
操作,你能做的最好的:
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)
這也是一種可能性,但說實話,有點醜陋。我想我會更好地使用平等功能。 – pimvdb
這並不像你想象的那麼醜陋,因爲你可能已經在你的對象上有一個'toString'函數,以便於調試。但是,再次,我只是寫了這個答案,因爲你說你更喜歡'=='操作符。功能。使用你最喜歡的東西。乾杯! :) – galambalazs
確實有一個toString函數,但對於平等檢查來說,執行v1.equalsTo(v2)要比記住你必須將它轉換爲一個String容易,因爲這不是通常的做法 - 非常感謝無論如何! – pimvdb
下面是一個簡單的仿真,其使用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中定義)的參數指定的數據的屬性的對象,其數字名稱值小於相應函數對象的形式參數的數量,最初與函數的執行上下文中的相應參數綁定共享它們的值。這意味着改變屬性會改變參數綁定的相應值,反之亦然。如果這樣的屬性被刪除然後重新定義或者屬性被改變爲訪問者屬性,則該對應關係被破壞。對於嚴格模式函數,參數對象的屬性值只是傳遞給函數的參數的副本,並且屬性值和形式參數值之間不存在動態鏈接。
參考
這不是你問題的直接答案,但值得注意。
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>
我意識到這一點是一箇舊的答案 - 不知道這與OP的問題有什麼關係? – brandonscript
雖然這可能是有用的知識,但這實際上並沒有回答這個問題。 –
您可以更改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
所以這不是你的問題的確切答案,但我認爲這可能是對這類問題有用的東西。
我最近發現使用JQuery進行鏈接,它在某些情況下非常有用,非常感謝您的示例! – pimvdb