Brad Woods Digital Garden

Notes / JavaScript / Types / Coercion

The Warhammer 40k Adeptus Mechanicus symbol

Table of contents

    The number 1, the number 1 with quotes and the word true

    JavaScript Coercion

    Planted: 

    Status: decay

    Hits: 66

    A type can be converted in 2 different ways:

    • Type casting: explicitly converting a value from 1 type to another. Occurs in statically typed languages at compile time. TypeScript example: const myVar = otherVar as string.
    • Coercion: occurs in dynamically typed languages, like JavaScript, at runtime. It can happen in 2 different ways:
      • explicit: it's obvious the intent is to convert a value from one type to another.
      • implicit: type conversion occurs as a side-effect of some operation.

    Example, coercing a number into a string:

    index.js

    const a = 42;
    // explicit coercion
    const c = String(a);
    // implicit coercion
    const b = a + "";

    Coercion is like translating a word from 1 language to another. For example, translating the word apple from English to German. A translator will look at all the words available in the German language. Then, pick 1 that best matches the English word's meaning. In this case, apfel.

    The translator is the JavaScript engine, the word is a value and the languages are JavaScript's types. Imagine the engine needs to coerce a value from a string to a boolean. The engine looks at the available "words" in the boolean "language". There are only 2, true or false. Whichever is selected, a lot of the string's meaning will be lost in translation. But that is the nature of coercion.

    Whenever coercion occurs, 1 or more internal operations, known as abstract operations, are performed. It always results in a primitive.

    Explicit Coercion

    To explicitly coerce a value to a string, number or boolean, use the built-in native contructors. The new keyword isn't used (so an object wrapper isn't created).

    index.js

    const a = 1;
    const b = String(a);
    const c = "1";
    const d = Number(c);
    const e = "1";
    const f = Boolean(c);

    These constructors can coerce any value to a primitive based on the rules of the abstract operations:

    • ToString
    • ToNumber
    • ToBoolean

    ToString

    The ToString abstract operation rules are:

    • null becomes "null"
    • undefined becomes "undefined"
    • true becomes "true"
    • number: 1 becomes "1". Very small or large numbers become their exponent form:

    index.js

    const a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
    const aStr = a.toString();
    // seven times three digits => 21 digits
    console.log(aStr)

    Object values have their own toString() method. If you implicitly coerce an object, its toString() will automatically be called.

    index.js

    const obj = [1,2];
    // explicit
    console.log(obj.toString())
    // implicit
    // if either operand to '+' is a string, the operation will be string concatenation
    console.log(obj + "")

    ToNumber

    The ToNumber abstract operation rules are:

    • true becomes 1
    • false becomes 0
    • undefined becomes NaN
    • null becomes 0
    • string: "1" becomes 1, "a" becomes NaN

    To coerce an Object value:

    1. 1. The ToPrimitive() abstract operation will check if the object has a valueOf() method.
      • if it exists and it returns a primitive value, that value will be used
      • if it doesn't exist, but toString() does, its return value will be used
      • if neither exist or don't return a primitive, a TypeError is thrown
    2. 2. The primitive value will be coerced as per the ToNumber rules above.

    index.js

    const objA = {
    valueOf: function(){
    return 1;
    }
    };
    const objB = {
    toString: function(){
    return "1";
    }
    };
    const objC = [4,2];
    objC.toString = function(){
    return this.join( "" );
    };
    console.log(Number(objA))
    console.log(Number(objB))
    console.log(Number(objC))
    console.log(Number([]))
    console.log(Number(["abc"]))

    parseInt

    parseInt(..) can be used to get a numeric value out of a string containing non-numeric characters. It parses left-to-right and stops when a non-numeric value is found.

    index.js

    const a = "42px";
    console.log(Number(a));
    console.log(parseInt(a));

    ToBoolean

    The ToBoolean abstract operation rules are:

    • undefined becomes false
    • null becomes false
    • +0, -0, and NaN becomes false
    • "" becomes false
    • all other values become true

    Boolean(myVar) or !!myVar can be used.

    index.js

    var myVar = 1;
    console.log(Boolean(myVar));
    console.log(!!myVar);

    Implicit Coercion

    Expression operations that are implicitly coerced to a boolean:

    • The test expression in an if (..) statement.
    • The test expression (2nd clause) in a for ( .. ; .. ; .. ) header.
    • The test expression in while (..) and do..while(..) loop.
    • The test expression (1st clause) in a ? : ternary expression.
    • The left-hand operand to the || and && operators.
    Ani's soul, represented by a bird with a human head, observes as Anubis weighs Ani's heart

    Equality

    When comparing 2 values for equality, commonly used operators are:

    • loose equality: ==
    • strict equality: ===

    Loose allows coercion. Strict doesn't.

    index.js

    const a = 42;
    const b = "42";
    console.log(a == b);
    console.log(a === b);

    Feedback

    Have any feedback about this note or just want to comment on the state of the economy?

    Where to next?

    JavaScript
    Arrow pointing downYOU ARE HERE
    A Johnny Cab pilot