在看红宝书的时候,测试{}<3时,发生了出乎意料的返回结果…
今天系统重新巩固红宝书,在词法的操作符版块,看到了关系操作符,兴致上来了自己测试了几个用例
1 | "23" < "3" // true |
我们先来看看红宝书上对该操作符的描述
- 如果两个操作数都是数值类型,则进行数值比较
- 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值
- 如果一个操作数是数值,则将另外一个转化为数值,然后再比较
- 如果一个操作符是对象,则调用valueOf,用得到的结果按照前面的规则执行比较,如果没有valueOf方法或者返回的值不是基本类型,则用toString方法
- 如果一个操作数是NaN则返回false,因为NaN不能比较
那么,我们来看一下{}<3
这个表达式,3是数值类型,那么我们就对另外一个值操作,先调用valueOf操作,返回{}不是基本数据类型,则调用toString方法,返回”[object Object]”是基本类型,现在变成了一个数值3和一个字符串”[object Object]”进行该操作,我们对字符串进行强制类型转换,转化为NaN,那么实际应该是NaN < 3,返回false才对,但是在chrome浏览器上则是抛出未知语法错误,我就产生了巨大的疑惑,难道是我哪一步推导产生了错误?
打开vsc写了一个脚本如下
1 | var o1 = { |
我自己在这里模拟了一个object,但是为什么在node下就没有报错呢?我又测试了一下更简单直接的版本
1 | console.log({} < 3) // false |
到这里才恍然大悟,原来之前的语法报错是chrome浏览器自己做的手段,跟ECMAScript规范没有关系
但是也要注意对象在这里的处理情况,并不是对象调用[ToPrimitive]属性直接作为返回值,而是将返回值再带入规则中,可能还要进行第二轮的类型转换
1 | var o1 = { |
上例中,”1”和2比较,套用规则,再将”1”转换成1之后进行比较
1 | var o1 = { |
上例中1和”a”比较,”a”转换为NaN,则返回false