覆盖JavaScript中比较运算符的默认行为

时间:2011-04-11 21:24:49

标签: javascript class inheritance object override

我有一个自定义Javascript类(使用John Resig's Simple Javascript Inheritance创建)。我希望能够使用==<>>=<=符号来比较此类的两个实例。

如何覆盖自定义类的比较器?

3 个答案:

答案 0 :(得分:9)

尝试覆盖valueOf()。然后你可以写这样的东西:

if (obj1.valueOf() === obj2.valueOf())
if (obj1.valueOf() < obj2.valueOf())
if (obj1.valueOf() > obj2.valueOf())

因此,每当我需要一个特殊的JavaScript对象类型来覆盖比较时,我只需将valueOf添加到原型中。它对于原始类型也很有用,因为valueOf只返回值。

请注意空值。

答案 1 :(得分:3)

这不可能以你所暗示的方式完成(虽然那会很好)。我看到这样做的最好方法是在原型上实现一组方法,就像比较一样:

gte : function( obj ){ // greater than or equal
  // return custom comparison with this as the object comparable on the left
},
gt : function( obj ){...}, // greater than but not equal
eq : function( obj ){...}, // equal to
// etc.

我今天在工作中正在考虑这个问题,并且有另一种方法可以利用标准比较运算符但是有自定义对象比较。诀窍是在对象上有一个表示可比状态的属性(getter)。这将要求在给定相同的可比较属性的情况下,对象的所有实例都评估为相同的数值。举一个例子,让我们谈谈向量:

function Vector(x,y,z){
  this.comp = function(){
    // assuming these are floats you may wish to create a comparable level of
    // precision. But this gets the point across.
    return x + (y * 10) + (z * 100);
  }
}

然后当你设置矢量时:

var v1 = new Vector(1,1,1);
var v2 = new Vector(1,0,1);
v1.comp() > v2.comp() // true

这当然只能处理可以分解为简单数值表达式的对象,但好处是获得基本效果的实现代码非常低,你甚至可以做到这一点使对象本身成为一个函数,返回它的组成部分的数字表达式。

function Vector(x,y,z){
  var v = function v(){
    return v.x + (v.y * 10) + (v.z * 100);
  }
  v.x = x;
  v.y = y;
  v.z = z;
  return v;
}

现在,通过简单的数字比较,您可以获得对象的所有好处,而且它甚至有点简洁。

答案 2 :(得分:3)

Lee是正确的,如果你实现valueOf然后在比较对象时(不是用===或!===)这将被使用,但是你也必须使用toString,因为它在排序数组时出于某种原因使用

function Test(value){
  this.value=value;
}
Test.prototype.toString=function(){
  console.log("tostring called");
  // could do something with case sensitiveness here
  return new String(this.valueOf());
}
Test.prototype.valueOf=function(){
  console.log("valueof called");
  return this.value;
}

var t1=new Test(11);
var t2=new Test(1.1);
var arr=[t1,t2];
console.log(arr.sort());
console.log(t1>=t2);