Under the hood of, JavaScript's Type Conversion
DEV Community

Under the hood of, JavaScript's Type Conversion

Explicit Type Conversion

JavaScript provides three functions for converting values explicitly. These return primitive values, not objects:

  1. Number(value)
  2. String(value)
  3. Boolean(value)

Examples:

Number("3")    // 3
String(false)  // "false"
Boolean([])    // true

Number()

Converts a value to a number:

Number("42")       // 42
Number(true)       // 1
Number(false)      // 0
Number(null)       // 0
Number(undefined)  // NaN
Number("abc")      // NaN

String()

Converts a value to a string:

String(42)        // "42"
String(true)      // "true"
String(null)      // "null"
String(undefined) // "undefined"

Boolean()

Converts a value to a boolean:

Boolean([])       // true
Boolean({})       // true
Boolean("0")      // true
Boolean("false")  // true

A special behaviour of boolean related to objects will be explained later.

Comparison with Number & String Wrapper

new Number(5) === 5        // false
new String(0) === String(0) // false
// because left side is an object; right side is a primitive

Comparison with Boolean Wrapper

new Boolean(true)
new Number(10)
new String("abc")
// These return objects.

typeof new Boolean(false) // "object"

So if you do:

const isFalse = Boolean(0) // false
if(isFalse) // false

vs.

const isFalse = new Boolean(0) // {false}
if(isFalse) // true

Why Do the Wrapper Objects Even Exist?

In the early days, JavaScript wanted the primitives to have methods. To fulfill this requirement, the language had wrappers. In modern JavaScript, primitives can't have methods. So, the engine optimizes this.

Why Should You Not Use new String(), new Number(), or new Boolean()?

const isFalsePrimitive = Boolean(0);
const isFalseObject = new Boolean(0);

if(isFalsePrimitive) // false
if(isFalseObject)    // true

Special Behaviour of Boolean

Because all objects are truthy, regardless of the value they wrap:

if([])  // true ; arrays are also objects in JS
if({})  // true

So, try not to use it and avoid confusion.

Explicit Conversions: Object to Primitive (Number, Boolean, String)

During type coercion/conversion, the JavaScript engine asks itself: "I need a primitive value, which primitive (string, number, bigint, symbol, boolean) should I use?"

The JavaScript engine has 3 options to choose from:

  1. Should I convert it to string? - uses .toString()
  2. Should I convert it to number? - uses .valueOf()
  3. Either string or number is acceptable - when it can't convert, return TypeError

Steps for Conversion

Before it is decided whether to convert to string first or not, the engine analyzes based on the "hint" given in the statement.

For example:

// 1. here the hint is '' to convert to string
'' + 10 // '10'

// 2. here the hint is Number()
Number('123') + 10 // 133

Second step is to analyze and see after using toString() or valueOf() the result is a primitive or not.

For example:

// 1. Needs primitive type number >> use valueOf(), if
// typeof result === number
// then return result, else use toString() and return it

Number({})
// final result NaN
// -->> converts to '[object Object]' because
// -->> valueOf() conversion returns {} which is not a number;
// so toString() prevails and gives
// -->> '[object Object]' which is string(primitive)
// -->> Number('[object Object]') is NaN

// here hint is +
{} + ''
// Parser sees: {} // empty block
// +'' // Unary plus
// Number("") // gives numeric 0

For Boolean, the engine only checks if typeof argument === object, if yes returns true.

For Dates, the default preference is to return a String:

Number(Date()) // 1789546456464 milliseconds
String(Date()) // Tue Jul 14... forced string conversion
console.log(Date()) // Tue Jul 14... default

The Diagram

Need Primitive
      โ”‚
      โ–ผ
Which Hint?
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
String?
      โ”‚
      โ–ผ
   toString()
      โ”‚
   Primitive?
      โ”‚        โ”‚
     Yes       No
      โ”‚        โ”‚
      โ–ผ        โ–ผ
   Return    valueOf()
                โ”‚
             Primitive?
              โ”‚        โ”‚
             Yes       No
              โ”‚        โ”‚
              โ–ผ        โ–ผ
           Return    TypeError

Next article will be based around the miscellaneous features of var vs let vs const keywords.

Comments

No comments yet. Start the discussion.