Переопределить поведение операторов сравнения по умолчанию в JavaScript
у меня есть пользовательский класс Javascript (созданный с помощью простое наследование Javascript Джона Resig). Я хочу иметь возможность сравнивать два экземпляра этого класса, используя ==
, <
, >
, >=
и <=
символы.
как переопределить компараторы моего пользовательского класса?
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;
}
теперь у вас есть все преимущества объекта с легкими числовыми сравнениями, и это даже немного кратко.
попробуйте переопределить valueOf (). Тогда вы можете написать такие вещи:
if (obj1.valueOf() === obj2.valueOf())
if (obj1.valueOf() < obj2.valueOf())
if (obj1.valueOf() > obj2.valueOf())
поэтому, когда мне нужен специальный тип объекта JavaScript для переопределения сравнения, я просто добавляю valueOf к прототипу. Он отлично работает для примитивных типов, так как стоимость просто возвращает значение.
просто следите за нулями.
ли прав, если вы реализуете 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);