这就是对象比较运算符的工作原理:
var a = {}, b = {};
a === b;
a == b;
a > b;
a < b;
var c = { valueOf : function () { return 0; } };
var d = { valueOf : function () { return 1; } };
c === d;
c == d;
c > d;
c < d;
底层实现
有点类似
第一部分:相等性
这是最简单的部分。抽象相等(==
,规范)和严格相等(===
,规范)都检查是否引用了相同的对象(比较引用)。在这种情况下,它们显然不是同一个对象,因此答案是false
(==
规范步骤10,===
规范步骤7)。
因此,在两种情况下:
b1 == b2 //false
b1 === b2 //false
第二部分:比较开始
这是有趣的部分。让我们看一下关系运算符(<
和 >
)是如何被定义的。在这两种情况下,让我们跟随调用链。
x = b1
y = b2
Let px be the result of calling ToPrimitive(x, hint Number).
Let py be the result of calling ToPrimitive(y, hint Number).
InputType is Object, therefore we call the internal [[DefaultValue]] method with hint Number.
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替换字符,表示“我不知道发生了什么”。这就是为什么它的十六进制等价物是FFF D。
显然,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
。
然而,由于小于和大于符号的工作方式,它们被转换为字符串(然后转换为数字)进行比较。根据第三点,在这种情况下它们是相同的值;因此,它们不能互相小于或大于,导致结果为 false
。
最后,只是为了让你开心:
b1 <= b2 //true
b1 >= b2 //true
b1
和b2
? - Zirak==
;相反,总是使用===
。 (2) 在JavaScript中除了undefined
、null
、true
、false
、数字(包括Infinity
但排除NaN
)和字符串外,没有等价测试;没有其他东西可以与===
有意义的比较,因为这本质上是一个值身份运算符。x === y
表示x
和y
共享相同的分配内存/是完全相同的对象。 否则x === y
始终为false
,因此例如[] === []
是false
。—另请参见我对接受的答案的评论,如下。 - flow