为什么 {} > [] ?
TLDR 版本
关系比较
在 JavaScript 中,关系比较的结果由抽象关系比较算法确定。该算法将比较的两边都转换为原始值,然后返回这两个原始值的比较结果。
ToPrimitive¹
抽象关系比较算法调用ToPrimitive
两次,每个操作数一次,并将“number”作为第二个参数传递。这告诉函数ToPrimitive
,如果操作数可以转换为多个基本类型,并且 number 是其中之一,则应该将值转换为数字,而不是其他类型。
普通到原始²
如果传递的值ToPrimitive
是一个对象,则它会OrdinaryToPrimitive
使用相同的两个参数(值和类型提示)进行调用。OrdinaryToPrimitive
生成一个方法列表,用于调用将值转换为原始值。
如果传入的是“string”作为类型提示,则方法顺序将变为toString
后跟valueOf
。在本例中,由于传入的是“number”,因此方法顺序将变为valueOf
后跟toString
。需要注意的是,虽然到达此处的所有值都是对象,但并非每个值都会使用Object原型上的valueOf
和方法。toString
如果第一个方法返回“object”类型的值,则返回第二个方法的调用结果。如果第一个方法没有返回“object”类型的值,则返回第一个方法的调用结果。
普通转原始({})
对于 {} 的情况,唯一被检查的原型是Object,因此它首先尝试使用³调用valueOf
对象,但返回的是 {}。由于 typeof {} === "object",它转到下一个方法。然后调用⁴ ;如果对一个对象值调用 ,则将内置标签设置为 "Object"。 的返回值是 [object ", tag, "] 的串联。因此,传入空对象的返回值为 [object Object]"Object.prototype.value()
Object.prototype.toString()
Object.prototype.toString()
Object.prototype.toString()
普通转原始( [] )
对于 [] 的情况,需要考虑两个原型—— Array 和 Object 。如果Array原型上存在某个方法,则调用该方法。但是,如果Array 原型上不存在该方法,则会在Object原型上查找该方法。Array原型不包含 的方法valueOf
,因此它首先尝试调用Object.prototype.valueOf()
。这将返回 [],由于 typeof [] === "object",因此它会转到下一个方法。
Array原型确实有一个toString()
方法,因此它会调用Array.prototype.toString()
⁵。
Array.prototype.toString()
返回数组上该方法的值join
。由于数组中没有元素,因此Array.prototype.toString()
空数组上的返回值为空字符串。
比较
现在双方都已转换为原始值,是时候对它们进行比较了。
"[object Object]" > ""
任何长度的字符串的值都将大于空字符串的值。
后续行动
当一个操作数的类型为 String/Number/Symbol/BigInt 而另一个操作数是对象时,JavaScript 评估抽象相等性的方式是ToPrimitive
对该对象调用相同的方法,然后检查相等性⁶。
因此,我们还可以通过执行抽象相等性检查来检查 {} 是否实际转换为"[object Object]"
空字符串,以及 [] 是否转换为空字符串。
console.log({} == "[object Object]") // true
console.log([] == "") // true
为什么浏览器中会出现 {} > [] 错误?
JavaScript 规范的编写方式是,块语句先于表达式求值,因此,当解释器在非表达式上下文中遇到花括号时,它会将其解释为块而不是对象字面量。这就是为什么在浏览器中运行这些表达式时会报错。强制解释器将 {} 视为对象字面量而不是块的方法是将其括在括号中。
如果您打开 Node 控制台而不是浏览器控制台,您将看到:
这是因为 Node 做了一些改动,先将输入作为表达式求值,然后再将其作为语句求值。该改动可在此处查看。
TLDR 版本
{}
转换为"[object Object]"
[]
转换为""
"[object Object]" > ""
参考:
³ Object.prototype.valueOf() 规范
⁴ Object.prototype.toString() 规范
⁵ Array.prototype.toString() 规范
鏂囩珷鏉ユ簮锛�https://dev.to/amyshackles/why-is-2hkk