在Javascript中覆盖等价比较

Lar*_*tle 34 javascript operator-overloading qunit

是否可以在Javascript中覆盖等价比较?

我得到的最接近的解决方案是定义valueOf函数并在对象前面用一个加号调用valueOf.

这有效.

equal(+x == +y, true);
Run Code Online (Sandbox Code Playgroud)

但这失败了.

equal(x == y, true, "why does this fail.");
Run Code Online (Sandbox Code Playgroud)

这是我的测试用例.

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.");
});
Run Code Online (Sandbox Code Playgroud)

在这里演示:http://jsfiddle.net/tWyHg/5/

Cor*_*ewe 22

这是因为==操作符不仅仅比较基元,因此不调用该valueOf()函数.您使用的其他运算符仅适用于基元.我担心你无法在Javascript中实现这样的功能.有关更多详细信息,请参见http://www.2ality.com/2011/12/fake-operator-overloading.html.


Noa*_*tas 14

捎带@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
Run Code Online (Sandbox Code Playgroud)

我知道这并不能完全符合您的要求(重新定义等效运算符本身),但希望它能让您更接近.

  • 注意 `NaN === NaN` 是假的。 (3认同)

CBu*_*Bus 5

如果它是您正在寻找的完整对象比较,那么您可能想要使用与此类似的东西。

/*
    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;
}
Run Code Online (Sandbox Code Playgroud)