Переопределить поведение операторов сравнения по умолчанию в JavaScript - PullRequest
8 голосов
/ 12 апреля 2011

У меня есть собственный класс Javascript (созданный с использованием Простого наследования JavaScript Джона Резига ).Я хочу иметь возможность сравнивать два экземпляра этого класса, используя символы ==, <, >, >= и <=.

Как переопределить компараторымой пользовательский класс?

Ответы [ 3 ]

9 голосов
/ 27 августа 2013

Попробуйте переопределить valueOf ().Затем вы можете написать что-то вроде этого:

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

Поэтому, когда мне нужен специальный тип объекта JavaScript для переопределения сравнения, я просто добавляю значение valueOf к прототипу.Он отлично работает и для примитивных типов, поскольку valueOf просто возвращает значение.

Просто следите за нулями.

4 голосов
/ 12 апреля 2011

это не может быть сделано так, как вы предполагаете, это должно быть сделано (хотя это было бы мило). Лучший способ, которым я видел это, - реализовать на прототипе набор методов, действующих как сравнительные:

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.

Я думал об этой проблеме еще сегодня на работе, и есть альтернативный способ воспользоваться преимуществами стандартных операторов сравнения, но иметь пользовательские сравнения объектов. Хитрость заключается в том, чтобы иметь свойство (получатель) объекта, представляющего сопоставимое состояние. Это потребует, чтобы все экземпляры объекта оценивались по одному и тому же числовому значению, учитывая одинаковые сопоставимые свойства. В качестве примера давайте поговорим о векторах:

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

теперь у вас есть все преимущества объекта с помощью простых числовых сравнений, и это даже несколько кратко.

3 голосов
/ 28 августа 2013

Ли правильно, если вы реализуете 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);
...