小于(<)、大于(>)、小于等于(<=)和大于等于(>=)这几个关系操作符用于对两个值进行比较,比较的规则与我们在数学课上所学的一样。这几个操作符都返回一个布尔值,如下面的例子所示:

var result1 = 5 > 3;    //true
var result2 = 5 < 3; //false

与ECMAScript中的其他操作符一样,当关系操作符的操作数使用了非数值时,也要进行数据转换或完成某些奇怪的操作。以下就是相应的规则。

  • 如果两个操作数都是数值,则执行数值比较。
  • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。
  • 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较。
  • 如果一个操作数是对象,则调用这个对象的valueOf() 方法,用得到的结果按照前面的规则执行比较。如果对象没冇valueOf() 方法,则调用toString() 方法,并用得到的结果根据前面的规则执行比较。
  • 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。

在使用关系操作符比较两个字符串时,会执行一种奇怪的操作。很多人都会认为,在比较字符串值时,小于的意思是“在字母表中的位置靠前”,而大于则意味着“在字母表中的位置靠后”,但实际上完全不是那么回事。在比较字符串时,实际比较的是两个字符串中对应位置的每个字符的字符编码值。经过这么一番比较之后,再返回一个布尔值。由于大写字母的字符编码全部小于小写字母的字符编码,因 此我们就会看到如下所示的奇怪现象:

var result3 = "Brick" < "alphabet";  //true

在这个例子中, 字符串”Brick”被认为小于字符串”alphabet”。原因是字母B的字符编码为66,而字母a的字符编码是97。如果要真正按字母表顺序比较字符串,就必须把两个操作数转换为相同的大小写形式(全部大写或全部小写),然后再执行比较,如下所示:

var result4 = "Brick".toLowerCase() < "alphabet".toLowerCase();  //false

通过将两个操作数都转换为小写形式, 就可以得出“alphabet”按字母表顺序排在”Brick”之前的正确判断了。

另一种奇怪的现象发生在比较两个数字字符串的情况下,比如下面这个例子:

var result5 = "23" < "3";  //true

确实, 当比较字符串”23”是否小于”3”时, 结果居然是true。这是因为两个操作数都是字符串,而字符串比较的是字符编码(”2”的字符编码是50,而”3”的字符编码是51)。不过,如果像下面例子中一样,将一个操作数改为数值,比较的结果就正常了:

var result6 = "23" < 3;    //false

此时,字符串”23”会被转换成数值23,然后再与3进行比较,因此就会得到合理的结果。在比较数值和字符串时,字符串都会被转换成数值,然后再以数值方式与另一个数值比较。当然,这个规则对前面的例子是适用的。可是,如果那个字符串不能被转换成一个合理的数值呢? 比如:

var result7 = "a" < 3;    //false because "a" becomes NaN

由于字母”a”不能转换成合理的数值, 因此就被转换成了NaN。根据规则, 任何操作数与NaN进行关系比较, 结果都是false。于是, 就出现了下面这个有意思的现象:

var result8 = NaN < 3;    //false
var result9 = NaN >= 3; //false

按照常理, 如果一个值不小于另一个值, 则一定是大于或等于那个值。然而, 在与NaN进行比较时,这两个比较操作的结果都返回了false。