47

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.");
});

デモはこちら: http://jsfiddle.net/tWyHg/5/

4

5 に答える 5

29

これは、==演算子がプリミティブのみを比較するわけではないため、valueOf()関数を呼び出さないためです。使用した他の演算子は、プリミティブのみで機能します。残念ながら、Javascript でそのようなことを達成することはできません。詳細については、 http://www.2ality.com/2011/12/fake-operator-overloading.htmlを参照してください。

于 2012-05-10T18:29:28.763 に答える
15

@Corkscreewe に便乗:

これは、オブジェクトを扱っており、等価演算子は、2 つのオブジェクトが何らかの形で等しいかどうかではなく、2 つの変数が同じオブジェクトを参照しているかどうかのみを比較するためです。

1 つの解決策は、変数の前に「+」を使用し、オブジェクトの valueOf メソッドを定義することです。これにより、各オブジェクトの valueOf メソッドが呼び出され、その値が Number に「キャスト」されます。あなたはすでにこれを見つけていますが、当然のことながら、あまり満足していないようです。

より表現力豊かな解決策は、オブジェクトに equals 関数を定義することです。上記の例を使用して:

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

私はこれがあなたが望んでいることを正確にしないことを知っています (等価演算子自体を再定義します) が、うまくいけば、もう少し近づくことができます.

于 2012-05-10T19:07:01.193 に答える
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;
}
于 2012-05-10T19:15:53.840 に答える
3

ES6Object.is()関数を使用して、オブジェクトのプロパティを確認できます。

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;
}
于 2017-01-01T18:51:28.083 に答える