top of page

Type Coercion and Conversion in JS

Writer's picture: Viq HusViq Hus

Introduction

Recently I took a Salesforce JavaScript exam and I thought, I've been working with JavaScript or over 10 years, this should be easy. Well it was not. It Made me realise how much I had overlooked within JavaScript. How some code I could be writing every day, but what is actually happening in that line of code?

I found some of the quirks of JavaScript so fascinating that I went and asked some expect JavaScript developers some of these questions, and surprise surprise, most of the them got them wrong. Here I will walk you thought a few of these findings. If you don't believe the code, feel free to open your browser console and execute the code for yourself.

Implicit and Explicit Type Conversion

There are 2 types of type conversions: explicit, where you go and manually convert from one type to another, e.g.

  parseInt('123');

Then there is implicit where the type is automatically converted, e.g.

  15 - '2'  //13

In the above example, the string '2' is automatically converted into a integer and the result would be 13. This is true for all mathematical operations apart from when using the + symbol. Here, instead of implicitly converting the string to a number, the number will be converted into a string and they'll both be concatenated. E.g.

  '15' + 2  //'152'

Now what if we tried adding (or other mathematical operations) a Boolean to a number? Well, the Boolean would be implicity converted to a number and a value of 'false' would evaluate to 0 and a 'true' value would evaluate to 1. E.g.

  15 + true  //16    15 + false   //15

Okay, that's enough examples. Let's look at some comprehensive description of these rules:

LOOSE EQUALITY OPERATOR

The loose equality operator (== or !=)is used to determine if two operands are equal or not. It coerces primitives to numbers except for null and undefined (null only loosely equals to null and undefined)

So if you ever use the == or != operators, primitives such as strings and Booleans will be coerced into numbers (implcity converted) and that's how they will be compared, where null and undefined are the exceptions. E.g.

  null == undefined  // true                Number(null) == Number(undefined)  // false

COMPARISON OPERATORS

A comparison operator (>=, >, <=, or <)are used to determine if one value is greater than, less than, or equal to the other value. It coerces primitives to numbers.

Similarly, using > style operators will coerce primitives to numbers.

LOGICAL OPERATORS

OR (||), AND (&&), and NOT (!) are logical operators used to determine if an expression evaluates to true or false. They coerce primitives to boolean.

Now using logical operators such as && will actually coerce primitives to Booleans.

E.g. you might want to test if one of your string has a value:

  'a' && 'b'  // 'a'    'a' && ''  //''    '0' && '1'  // '1'

The above example will be evaluated as true, even though we have a 0 but because it is a string, it is treated as true.

ARITHMETIC OPERATORS

Arithmetic operators (-, +, /, and *)are used to subtract, add, divide, ormultiply values. They coerce primitives to numbers,except when + is used, if one operand is a string, the result is a string.

This is similar to the original examples we looked at the beginning of the section.

  true – 1  // 0

True is coerced to a number to 1 and minus 1, you have 0.

Things that will catch you out:

Look out for the following, these are where people are really caught out:

  NaN == NaN  //false    Number('abc') == NaN  //false

NaN is never equal to anything. If you need to check if a value is not a number, you need to use :

  Number.isNaN(NaN)  // true

Empty objects and empty arrays are coerced to true, even if they are empty:

  Boolean({})  // true    Boolean([])  // true

When coercing an object to a number, the valueOf() function is called on the object. So you could do the following:

  var objOne = { valueOf() { return 123 }}  objOne == 123  // true  Number(objOne)  // 123

If the valueOf() function returns a primitive, it will be used, else the toString() function will be called:

  var objOne = { valueOf() { return {} }, toString() { return 123 }}  Number(objOne)  // 123

The toString() method will always be called first though if you are converting to a date:

  var objOne = { valueOf() { return Date.now() - 10000 }, toString() { return Date.now }}  Date(objOne)  // 'Fri Dec 24 2021 12:25:21 GMT+0000 (Greenwich Mean Time)'                  

But doing the following:

  {} == {}  // false

This is because even though the objects look the same, they both have references to different objects. To compare 2 objects, you could use JSON.Stringify():

  JSON.stringify({}) == JSON.stringify({})  // true

Just remember though that functions on the objects won’t be stringified.

Happy coding!

18 views0 comments

Comments


I'm a lead software developer currently working at AG Grid in London.

Technologies I'm currently focused on include Salesforce, .NET Core, Angular, SQL, React and Azure.

Other than that, in my spare time I watch the Arsenal at the Emirates, work on side projects or watch sports. Oh, and I'm also a part-time body builder.

You can contact me at vh@viqas.co.uk

profile.jpg

About Viqas Hussain

© 2023 Viqas.co.uk. All Rights Reserved.

bottom of page