是否可以在Javascript中覆盖等效比较?
我最接近解决方案的方法是定义valueOf函数并使用对象前面的加号调用valueOf。
这很有效。
equal(+x == +y, true);
但这失败了。
equal(x == y, true, "why does this fail.");
以下是我的测试用例。
var Obj = function (val) {
this.value = val;
};
Obj.prototype.toString = function () {
return this.value;
};
Obj.prototype.valueOf = function () {
return this.value;
};
var x = new Obj(42);
var y = new Obj(42);
var z = new Obj(10);
test("Comparing custom objects", function () {
equal(x >= y, true);
equal(x <= y, true);
equal(x >= z, true);
equal(y >= z, true);
equal(x.toString(), y.toString());
equal(+x == +y, true);
equal(x == y, true, "why does this fails.");
});
答案 0 :(得分:19)
这是因为==
运算符不仅仅比较基元,因此不会调用valueOf()
函数。您使用的其他运算符仅适用于基元。我担心你无法在Javascript中实现这样的功能。有关更多详细信息,请参阅http://www.2ality.com/2011/12/fake-operator-overloading.html。
答案 1 :(得分:13)
在@Corkscreewe上捎带:
这是因为你正在处理对象,而等价运算符只会比较两个变量是否引用同一个对象,而不是两个对象是否在某种程度上相等。
一种解决方案是在变量前面使用“+”,并为Objects定义valueOf方法。这会调用每个对象上的valueOf方法将其值“强制转换”为Number。你已经发现了这一点,但可以理解的是它似乎并不满意。
更具表现力的解决方案可能是为对象定义一个等于函数。使用上面的示例:
Obj.prototype.equals = function (o) {
return this.valueOf() === o.valueOf();
};
var x = new Obj(42);
var y = new Obj(42);
var z = new Obj(10);
x.equals(y); // true
x.equals(z); // false
我知道这并不能完全符合您的要求(重新定义等效运算符本身),但希望它能让您更接近。
答案 2 :(得分:2)
如果你正在寻找完整的对象比较,那么你可能想要使用类似的东西。
/*
Object.equals
Desc: Compares an object's properties with another's, return true if the objects
are identical.
params:
obj = Object for comparison
*/
Object.prototype.equals = function(obj)
{
/*Make sure the object is of the same type as this*/
if(typeof obj != typeof this)
return false;
/*Iterate through the properties of this object looking for a discrepancy between this and obj*/
for(var property in this)
{
/*Return false if obj doesn't have the property or if its value doesn't match this' value*/
if(typeof obj[property] == "undefined")
return false;
if(obj[property] != this[property])
return false;
}
/*Object's properties are equivalent */
return true;
}
答案 3 :(得分:2)
you can use Es6 Object.is() function to check the property of object.
Object.prototype.equals = function(obj)
{
if(typeof obj != "Object")
return false;
for(var property in this)
{
if(!Object.is(obj[property], this[property]))
return false;
}
return true;
}
答案 4 :(得分:-2)
添加();
可能会有所帮助。
var Obj = function (val) {
this.value = val;
}();