ES5 规范 11.8.5 节定义了“抽象关系比较”(abstract relational comparison),分为两个部分:比较双方都是字符串(后半部分)和其他情况(前半部分)。
    比较双方首先调用 ToPrimitive,如果结果出现非字符串,就根据 ToNumber 规则将双方强制类型转换为数字来进行比较。

    1. var a = [ 42 ];
    2. var b = [ "43" ];
    3. a < b; // true
    4. b < a; // false

    如果比较双方都是字符串,则按字母顺序来进行比较:

    1. var a = [ "42" ];
    2. var b = [ "043" ];
    3. a < b; // false

    ab 并没有被转换为数字,因为 ToPrimitive 返回的是字符串,所以这里比较的是 "42""043" 两个字符串,它们分别以 "4""0" 开头。因为 "0" 在字母顺序上小于 "4",所以最后结果为 false。同理:

    1. var a = [ 4, 2 ];
    2. var b = [ 0, 4, 3 ];
    3. a < b; // false

    a 转换为 "4, 2"b 转换为 "0, 4, 3",同样是按字母顺序进行比较。再比如:

    1. var a = { b: 42 };
    2. var b = { b: 43 };
    3. a < b; // false

    因为a是[object Object],b也是[object Object],所以按照字母顺序a < b 并不成立。
    下面一些奇怪的例子:

    1. var a = { b: 42 };
    2. var b = { b: 43 };
    3. a < b; // false
    4. a == b; // false
    5. a > b; // false
    6. a <= b; // true
    7. a >= b; // true

    因为根据规范a <= b被处理为b < a,然后将结果反转。因为b < a的结果是false,所以 a <= b 的结果是 true
    js中 <= 是“不大于”的意思(即 !(a > b),处理为 !(b < a))。同理 a >= b 处理为 b <= a
    相等比较有严格相等,关系比较却没有“严格关系比较”(strict relational comparison)。也就是说如果要避免a < b中发生隐式强制类型转换,我们只能确保ab为相同的类型,除此之外别无他法。
    ===== 的完整性检查一样,我们应该在必要和安全的情况下使用强制类型转换,如: 42 < "43"。换句话说就是为了保证安全,应该对关系比较中的值进行显式强制类型转换:

    1. var a = [ 42 ];
    2. var b = "043";
    3. a < b; // false -- 字符串比较!
    4. Number( a ) < Number( b ); // true -- 数字比较!