覆盖 JavaScript 中比较运算符的默认行为
Posted
技术标签:
【中文标题】覆盖 JavaScript 中比较运算符的默认行为【英文标题】:Override default behavior of comparison operators in JavaScript 【发布时间】:2011-08-03 10:05:38 【问题描述】:我有一个自定义的 javascript 类(使用 John Resig's Simple Javascript Inheritance 创建)。我希望能够使用==
、<
、>
、>=
和<=
符号来比较此类的两个实例。
如何覆盖自定义类的比较器?
【问题讨论】:
在 Javascript 中,=
不是比较器,它是赋值运算符。
糟糕,错字。感谢收看。
查看文章底部:“这个主题将在我的工作中深入讨论:JavaScript Ninja 的秘密。将于 2008 年秋季发布。 " - 仍未发行,Resig 的书是 JavaScript 的永远的毁灭公爵 :)
比较如何?标准是什么?
Overloading Arithmetic Operators in JavaScript?的可能重复
【参考方案1】:
这不能以您暗示的方式来完成(尽管那会很好)。我见过的最好的方法是在原型上实现一组方法来表现得像比较:
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;
现在您可以通过简单的数字比较获得对象的所有好处,而且它甚至有点简洁。
【讨论】:
我很怀疑:/ 还是谢谢。 不久前,我看到了一种在 Javascript 中实现运算符重载的 hacky 方法:blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx 我一直想尝试一下,看看是否可以改进它,但我一直没有解决给它。 @PeterOlson 该链接不再有效。我想读一下,如果你找到了,你会转发吗?谢谢。 @Gabriel Here's a post 有点像现在消失的那个。【参考方案2】:尝试覆盖valueOf()。然后你可以写这样的东西:
if (obj1.valueOf() === obj2.valueOf())
if (obj1.valueOf() < obj2.valueOf())
if (obj1.valueOf() > obj2.valueOf())
所以每当我需要一个特殊的 JavaScript 对象类型来覆盖比较时,我只需将 valueOf 添加到原型中。它也适用于原始类型,因为 valueOf 只返回值。
注意空值。
【讨论】:
valueOf 的好处是你不需要显式调用它 obj1 > obj2 会为你调用 valueOf。在对数组进行排序时,有时会调用 toString(在 FF 上),所以也要实现它。【参考方案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('sorted',arr.sort().map(o=>o.value));
console.log('larger',t1>=t2);
【讨论】:
以上是关于覆盖 JavaScript 中比较运算符的默认行为的主要内容,如果未能解决你的问题,请参考以下文章
覆盖 UIActivityViewController 默认行为