skip to Main Content

Consider the following example.

const x = false;
const y = "1";
const z = {};

console.log(x < y); // true
console.log(y < z); // true
console.log(x < z); // false

Since x < y and y < z both evaluate to true, I expected x < z to evaluate to true too because I thought < was transitive. I was wrong. The < operator in JavaScript is not transitive. Hence, JavaScript values don’t form an ordered set. Not even a partially ordered set.

Anyway, I understand why false < "1" evaluates to true. The false is coerced to 0 and the "1" is coerced to 1. What I don’t understand is why "1" < {} evaluates to true, and why false < {} evaluates to false. Could you explain how these three expressions are evaluated, and how the < operator works in JavaScript?

3

Answers


  1. In the case of "1" < {}, the object {} is not directly comparable, so JavaScript converts the object to a string using the default toString method.

    Image of conversion of {} to a string using toString Method

    So then comparing "1" < {}.toString which gives us true, since when comparing "1" (U+0031) comes before "[" (U+005B) alphabetically. Hence the output will be true.

    Similarly, for the condition false < {}, while comparing an object with a boolean, the value for the object is NaN.
    And hence 0 < NaN which evaluates to false.

    Login or Signup to reply.
  2. The less than (<) operator returns true if the left operand is less than the right operand, and false otherwise.
    Let’s see examples of comparisons different types of values.
    String to string comparison

    "a" < "b"; // true
    "a" < "a"; // false
    "a" < "3"; // false
    "uD855uDE51" < "uFF3A"; // true
    

    String to number comparison

    "5" < 3; // false
    "3" < 3; // false
    "3" < 5; // true
    
    "hello" < 5; // false
    5 < "hello"; // false
    
    "5" < 3n; // false
    "3" < 5n; // true
    

    Comparing Boolean, null, undefined, NaN

    true < false; // false
    false < true; // true
    
    0 < true; // true
    true < 1; // false
    
    null < 0; // false
    null < 1; // true
    
    undefined < 3; // false
    3 < undefined; // false
    
    3 < NaN; // false
    NaN < 3; // false
    

    Also you must know!

    • First, objects are converted to primitives by calling its @@toPrimitive (with "number" as hint), valueOf(), and toString() methods, in that order. The left operand is always coerced before the right one. Note that although @@toPrimitive is called with the "number" hint (meaning there’s a slight preference for the object to become a number), the return value is not converted to a number, since strings are still specially handled.
    • If both values are strings, they are compared as strings, based on the values of the UTF-16 code units (not Unicode code points) they contain.
    • Otherwise JavaScript attempts to convert non-numeric types to numeric values:
      Boolean values true and false are converted to 1 and 0 respectively.
      null is converted to 0.
      undefined is converted to NaN.
      Strings are converted based on the values they contain, and are converted as NaN if they do not contain numeric values.
    • If either value is NaN, the operator returns false.
    • Otherwise the values are compared as numeric values. BigInt and number values can be compared together.

    I hope, helped you. I picked up answer from here

    Login or Signup to reply.
  3. JS tries to compare as numbers if any of the operands is numerish (boolean, number, date), if that fails (for example a string cannot be converted to a number or an operand is an object), it compares as strings.

    For objects toString() method is used to convert an object to a string so if you provide a numeric string you can actually make an object comparable as a number, the Numerish example shows how you can change result of the previous comparing a boolean with an object.

    Moreover an object can implement valueOf() method and return actual number.
    In that case the comparison will be tried as numeric. The Numeric example shows that.

    const x = false;
    const y = "1";
    const z = {};
    
    console.log(x < y); // true since 0 < 1 ('1' converted to 1)
    console.log(y < z); // true since '1' < '[object Object]' ({} converted to a string)
    console.log(x < z); // false since 'false' > '[object Object]' ({} cannot be converted to a number, so false converted to a string)
    
    console.log('-1' > false); // false, since -1 < 0
    console.log('-100' < '-200') // true, compared as strings
    
    class Numerish{
      constructor(number){
        this.number = number;
      }
      toString(){
        return this.number;
      }
    }
    
    const num = new Numerish(1);
    
    console.log(x < num); // true since toString() is used and 0 < '1'
    
    class Numeric{
      constructor(number){
        this.number = number;
      }
      valueOf(){
        return this.number;
      }
    }
    
    const num2 = new Numeric(2);
    
    console.log('11' > num2); // true compared as 11 > 2, though '11' > '2' is false
    
    console.log(' ' > -1); // true since Number(' ') === 0 so 0 > -1
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search