【问题标题】:Override the Equivalence Comparison in Javascript覆盖 Javascript 中的等价比较
【发布时间】:2012-05-19 09:01:32
【问题描述】:

是否可以覆盖 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/

【问题讨论】:

  • 你到底想在这里实现什么?
  • @ElliotBonneville 我正在用 javascript 创建分数对象。
  • 分数对象是什么样的?我们可以看到一些示例输入吗?或者也许我只是误解了你想要做什么......
  • @ElliotBonneville 基本上我试图让用户使用直接比较而不是在对象上调用比较函数。这很奇怪,因为 >、=、
  • @ElliotBonneville 这是我使用这些技术创建的。 Ratio.js github.com/LarryBattle/Ratio.js

标签: javascript operator-overloading qunit


【解决方案1】:

这是因为== 运算符不只比较原语,因此不调用valueOf() 函数。您使用的其他运算符仅适用于原语。恐怕你不能用 Javascript 实现这样的事情。有关更多详细信息,请参阅http://www.2ality.com/2011/12/fake-operator-overloading.html

【讨论】:

  • == 调用 ToPrimitive 调用 valueOf if == 的一侧是非对象
  • 问题是Is it possible to override the equivalence comparison in Javascript?
【解决方案2】:

捎带@Corkscreewe:

这是因为您正在处理对象,而等价运算符只会比较两个变量是否引用同一个对象,而不是两个对象是否相等。

一种解决方案是在变量前面使用“+”并为对象定义一个 valueOf 方法。这会调用每个对象的 valueOf 方法以将其值“转换”为数字。您已经找到了这个,但可以理解的是,似乎对它不太满意。

一个更具表现力的解决方案可能是为您的对象定义一个 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

我知道这并不完全符合您的要求(重新定义等价运算符自己),但希望它能让您更接近一点。

【讨论】:

  • 注意NaN === NaN 是假的。
【解决方案3】:

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

/*
    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;
}

【讨论】:

    【解决方案4】:

    你可以使用 ES6 Object.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;
    }
    

    【讨论】:

      【解决方案5】:

      添加 (); 可能会有所帮助,具体取决于您的要求。

      var Obj = function (val) {
          this.value = val;
      }();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-13
        • 2011-08-03
        • 1970-01-01
        • 2012-03-25
        • 1970-01-01
        • 2013-04-18
        • 2011-01-08
        • 1970-01-01
        相关资源
        最近更新 更多