Technology · JavaScript

Intermediate

JavaScript Type Coercion

Understand how JavaScript converts types automatically and avoid common equality and comparison bugs.

TL;DR
  1. 01Compare values with === to avoid surprise type conversions.
  2. 02Learn which values count as falsy in conditionals.
  3. 03Convert types explicitly with Boolean, Number, and String.

Loose vs Strict Equality

  • Use === to compare both value and type with zero implicit conversion.
    console.log(1 === 1);   // true
    console.log(1 === '1'); // false
    
  • Use == carefully, since it converts operands to a common type before comparing.
    console.log(1 == '1');  // true
    console.log(0 == false); // true
    
  • Compare null and undefined with == only when checking for either value at once.
    function isMissing(value) {
      return value == null; // true for both null and undefined
    }
    
  • Always prefer !== over != for the same reason strict equality beats loose equality.
    console.log('5' !== 5); // true, different types
    
  • NaN never equals anything, even itself, under either equality operator.
    console.log(NaN === NaN); // false
    console.log(Number.isNaN(NaN)); // true
    

Truthy and Falsy Values

  • JavaScript treats every value as either truthy or falsy when used in a boolean context.
    if ('hello') {
      console.log('runs, because non-empty strings are truthy');
    }
    
  • Memorize the eight falsy values: false, 0, -0, 0n, '', null, undefined, and NaN.
    [false, 0, -0, 0n, '', null, undefined, NaN].forEach(v =>
      console.log(Boolean(v)) // always false
    );
    
  • Empty arrays and empty objects are truthy, which surprises many developers.
    if ([]) console.log('runs'); // [] is truthy
    if ({}) console.log('runs'); // {} is truthy
    
  • Check array length explicitly instead of relying on the array itself being falsy.
    const items = [];
    if (items.length === 0) console.log('empty array');
    
  • Use the double negation trick !!value to force a quick conversion to a real boolean.
    console.log(!!'text'); // true
    console.log(!!0);      // false
    

Implicit Conversion

  • The + operator concatenates strings when either operand is a string.
    console.log(1 + '1'); // "11"
    console.log('a' + 1); // "a1"
    
  • Subtraction, multiplication, and division force both operands toward numbers.
    console.log('5' - 2); // 3
    console.log('5' * '2'); // 10
    
  • Comparing a string and a number with relational operators converts the string to a number first.
    console.log('10' > 5); // true
    
  • Template literals always convert embedded expressions to strings automatically.
    const age = 30;
    console.log(`Age: ${age}`); // "Age: 30"
    
  • Objects convert to primitives using valueOf() or toString() during arithmetic or string operations.
    const obj = { valueOf: () => 42 };
    console.log(obj + 1); // 43
    

Explicit Conversion

  • Use Boolean(value) to convert any value to true or false explicitly.
    console.log(Boolean(''));  // false
    console.log(Boolean('0')); // true, non-empty string
    
  • Use Number(value) to convert strings or other types into a numeric value.
    console.log(Number('42'));   // 42
    console.log(Number('abc'));  // NaN
    
  • Use String(value) to convert any value into its string representation.
    console.log(String(42));    // "42"
    console.log(String(null));  // "null"
    
  • Use parseInt() or parseFloat() when a string has trailing non-numeric characters.
    console.log(parseInt('42px', 10)); // 42
    console.log(Number('42px'));       // NaN
    
  • Prefer explicit conversion over relying on implicit coercion, since it documents intent for future readers.
    const total = Number(input.value) + 10; // clear and predictable
    

Common Gotchas

  • An empty array loosely equals false because both reduce to 0 during comparison.
    console.log([] == false); // true
    
  • Adding two arrays together converts both to strings and concatenates them.
    console.log([1, 2] + [3, 4]); // "1,23,4"
    
  • null and undefined are loosely equal to each other but to nothing else.
    console.log(null == undefined); // true
    console.log(null == 0);         // false
    
  • typeof null famously returns "object", a long-standing JavaScript quirk.
    console.log(typeof null); // "object"
    
  • Comparing objects, even with identical contents, checks reference equality, not structural equality.
    console.log({ a: 1 } === { a: 1 }); // false
    
Tips
  1. 01Use strict equality with three equals signs by default so comparisons never silently convert types behind your back.
  2. 02Convert values explicitly with Number(), String(), or Boolean() so your intent is obvious to anyone reading the code.
  3. 03Check for NaN with Number.isNaN() instead of equality, since NaN never equals anything, including itself.
Warnings
  1. 01Loose equality with two equals signs converts types before comparing, which produces confusing results like '0' == false.
  2. 02Empty arrays and objects are truthy even though they look empty, so don't test them directly in an if statement.
  3. 03Adding a number and a string triggers string concatenation instead of arithmetic, often producing unexpected text output.
FAQ
JavaScript TimersJavaScript WeakMap and WeakRef