为什么在 ECMAscript 中函数 <= 函数为真,但 NaN <= NaN 为假

Ric*_*ick 4 javascript

我试图理解比较函数的奥秘:

let a=function(){}
let b=function(){}
console.log(a==b)  //false
console.log(a===b) //false
console.log(a<b)   //false
console.log(a>b)   //false
console.log(a<=b)  //true !?!
console.log(a>=b)  //true !?!

console.log( (+a) <  (+b) )  //false
console.log( (+a) >  (+b) )  //false
console.log( (+a) <= (+b) )  //false
console.log( (+a) >= (+b) )  //false
Run Code Online (Sandbox Code Playgroud)

在 ECMAscript 中,<= 操作符是这样描述的

RelationalExpression:RelationalExpression<=ShiftExpression

  1. 让 lref 是评估 RelationalExpression 的结果。
  2. 让 lval ? 获取值(lref)。
  3. 让 rref 是评估 ShiftExpression 的结果。
  4. 让 rval ? 获取值(参考)。
  5. 令 r 是执行抽象关系比较 rval < lval 且 LeftFirst 等于 false 的结果。
  6. ReturnIfAbrupt(r)。
  7. 如果 r 为真或未定义,则返回假。否则,返回真。

抽象关系比较似乎对字符串和 BigInts 有特殊情况,但我认为其他一切都应该转换为数字。所以我希望第二组比较与第一组等价,但事实并非如此。我错过了什么?

Pau*_*aul 6

抽象关系比较在参数上调用ToPrimitive并带有'number'. 然后再次调用OrdinaryToPrimitive并带有提示'number'.

这里的提示实际上只是一个提示;不要求例程返回该类型。的提示'number'只是导致 OrdinaryToPrimitive 尝试调用valueOfbefore toString,但toString如果valueOf不返回原语,它仍然会最终调用。

如果您提供一个返回原语的 valueOf 实现,它将用于比较:

let a=function(){}
let b=function(){}

a.valueOf = () => 1;
b.valueOf = () => 0;

console.log( a <= b );
console.log( b <= a );
Run Code Online (Sandbox Code Playgroud)

默认情况下,函数的 valueOf 返回函数本身,它不是原始函数,因此调用 toString 并将函数作为字符串进行比较。