这就是比较运算符在对象上的工作方式:
var a = {}, b = {};
a === b; //false
a == b; //false
a > b; //false
a < b; //false
var c = { valueOf : function () { return 0; } };
var d = { valueOf : function () { return 1; } };
c === d; //false
c == d; //false
c > d; //false
c < d; //true
在引擎盖下
(有点)
第 1 部分:平等
这是最简单的部分。抽象相等 ( ==
, spec ) 和严格相等 ( ===
, spec ) 都会检查您是否指的是同一个对象(比较引用的一种)。在这种情况下,他们显然不是,所以他们的回答是false
(==
规范步骤 10,===
规范步骤 7)。
因此,在这两种情况下:
b1 == b2 //false
b1 === b2 //false
第 2 部分:比较反击
有趣的部分来了。让我们看看关系运算符 (<
和>
)是如何定义的。让我们关注这两种情况下的调用链。
x = b1 //<Buffer aa>
y = b2 //<Buffer ab>
//11.8.5 The Abstract Relational Comparison Algorithm (http://es5.github.com/#x11.8.5)
Let px be the result of calling ToPrimitive(x, hint Number).
Let py be the result of calling ToPrimitive(y, hint Number).
//9.1 ToPrimitive (http://es5.github.com/#x9.1)
InputType is Object, therefore we call the internal [[DefaultValue]] method with hint Number.
//8.12.8 [[DefaultValue]] (hint) http://es5.github.com/#x8.12.8
We try and fetch the object's toString method. If it's defined, call it.
到这里我们已经到了高潮:什么是缓冲区的toString
方法?答案深藏在 node.js 内部。如果你想,就去吧。我们可以通过实验简单地发现:
> b1.toString()
'�'
> b2.toString()
'�'
好吧,那没有帮助。您会注意到,在抽象关系比较算法(多么花哨的名字<
)中,有一个处理字符串的步骤。它只是将它们转换为它们的数值 - 字符代码。让我们这样做:
> b1.toString().charCodeAt(0)
65533
> b2.toString().charCodeAt(0)
65533
65533 是一个重要的数字。它是两个平方的和:142^2 + 213^2
。它也恰好是 Unicode 替换字符,一个表示“我不知道发生了什么”的字符。这就是为什么它的十六进制等价物是 FFFD。
显然,65533 === 65533
,所以:
b1 < b2 //is
b1.toString().charCodeAt(0) < b2.toString().charCodeAt(0) //is
65533 < 65533 //false
b1 > b2 //following same logic as above, false
就是这样。
哥们,什么鬼?
好的,这一定很令人困惑,因为我的解释努力没有经过深思熟虑。回顾一下,这就是发生的事情:
您创建了一个缓冲区。Benjamin Gruenbaum通过执行以下操作帮助我重新创建了您的测试用例:
var b1 = new Buffer([170]), b2 = new Buffer([171]);
输出到控制台时,这些值将转换为等效的十六进制(请参阅Buffer#inspect):
170..toString(16) === 'aa'
171..toString(16) === 'ab'
但是,在内部,它们表示无效字符(因为它不是十六进制编码;同样,您可以自由地深入研究实现细节,我不会(哦,讽刺的是))。因此,当转换为字符串时,它们用 Unicode 替换字符表示。
由于它们是不同的对象,因此任何相等运算符都会返回false
.
但是,由于小于和大于的工作方式,它们被转换为字符串(然后转换为数字)进行比较。鉴于第 3 点,这是相同的值;因此,它们不能小于或大于彼此,导致false
.
最后,只是为了让你的脸上露出笑容:
b1 <= b2 //true
b1 >= b2 //true