The Reference Specification Type and Type Conversions in JavaScript
Tags: javascript
Published: 2020-02-06 10:45:24

Reference Specification Type

A **Reference** is a resolved name binding.

It is made up of 3 components:

* Base Value: (**Type:** **`undefined`**, **`Object`**, **`Number`**, **`String`**, **`Boolean`**, Environment Record). A base value of **`undefined`** means the _reference_ could not be resolved to a binding.
* Referenced name: (**Type:** **`String`**) The name given to the reference.
* Strict reference flag: (**Type:** **`Boolean`**)

# Type Conversions in JavaScript

The JavaScript runtime system performs automatic **type conversions** as needed.

Conversion can be done to primitive types as per the following rules:

* **ToBoolean**

This converts the argument to Boolean type.

    //falsy values in JavaScript
    console.log(Boolean(undefined));// false
    console.log(Boolean(null));// false
    console.log(Boolean(0));// false
    console.log(Boolean(+0));// false
    console.log(Boolean(-0));// false
    console.log(Boolean(""));// false
    console.log(Boolean(false));// false
    
    //truthy values in JavaScript
    console.log(Boolean(true));// true
    console.log(Boolean("Hello"));// true
    console.log(Boolean(4));// true
    console.log(Boolean(+Infinity));// true
    console.log(Boolean(-Infinity));// true
    console.log(Boolean("0"));// true
    console.log(Boolean({}));// true
    

* **ToNumber** This converts the argument to Number type.

    console.log(Number(undefined));// NaN
    console.log(Number(null));// 0
    console.log(Number(0));// 0
    console.log(Number(+0));// 0
    console.log(Number(-0));// -0
    console.log(Number(""));// 0
    console.log(Number(true));// 1
    console.log(Number("Hello"));// NaN
    console.log(Number(4));// 4
    console.log(Number(+Infinity));// Infinity
    console.log(Number(-Infinity));// -Infinity
    console.log(Number("0"));// 0
    console.log(Number({}));// NaN
    

* **ToString** This converts the argument to String type

    console.log(String(undefined));// undefined
    console.log(String(null));// null
    console.log(String(0));// 0
    console.log(String(+0));// 0
    console.log(String(-0));// 0
    console.log(String(""));// <empty string>
    console.log(String(true));// true
    console.log(String("Hello"));// Hello
    console.log(String(4));// 4
    console.log(String(+Infinity));// Infinity
    console.log(String(-Infinity));// -Infinity
    console.log(String("0"));// 0
    console.log(String({}));// [object Object]
    

* **ToObject**

This converts the argument to String type. Trying to convert **`undefined`** and **`null`** to Object type will result in **`TypeError`** exception.

An interesting thing to note about JavaScript is a numeric character within quotes gets converted to **`Number`** type in the below scenario:

    var varA = "8"+"0";
    console.log(varA); //80
    console.log("typeof varA is " + (typeof varA));//typeof varA is string 
    // this is a way of string concatenation in Javascript
    
    var varB = +"8" + +"0"
    console.log(varB);//8
    console.log("typeof varB is " + (typeof varB));//typeof varB is number
    
    varC = "88";
    console.log(typeof +varC);//number
    

Also we have spoke about the _Reference Specification Type_ , now it is important to note that :

_Primitive types in JavaScript are always passed by value_

_Objects types in JavaScript are always passed by reference_

Let's see examples to prove this:

    var a = 20;
    var b = a;
    console.log(a);// 20
    console.log(b);// 20
    a= 90;
    console.log(a);// 90
    console.log(b);// 20
    

Here when the assignment **`var b = a;`** was done, JavaScript executed this code in the below steps:

1. Create a variable reference.
2. Add the named reference of the variable created in step 1 as **`b`**
3. **Copy the value** of variable referenced by the named reference **`a`** to the variable with named reference **`b`**

Let's see another example of primitives:

    var c = 77;// 77
    console.log(c);
    function ChangeNum(x){
        x = 88;
    }
    ChangeNum(c);
    console.log(c);// 77
    

This further proves our point. Now let us try it on Object and Object properties:

    var objB = objA;
    console.log(objA);//{ prop1: 'aProp' }
    console.log(objB);//{ prop1: 'aProp' }
    //now we will change "prop1" property of object referenced by objB and see if objA also gets changed
    objB.prop1 = "bProp";
    console.log(objA);//{ prop1: 'bProp' }
    console.log(objB);//{ prop1: 'bProp' }
    

This confirms that objects get passed around by reference. Now let us assign a different object to objA. In this case will **`objB`** loose the reference to the previous object? Let's see

    objA = {
        differentProp1 : "differentA"
    }
    console.log(objA);//{ differentProp1: 'differentA' }
    console.log(objB);//{ prop1: 'bProp' }
    

**No it does not**. It is still pointing to the same memory location as it was earlier. but **`objA`** now points to a different location in the memory because the **`=`** operator changes the reference named **`objA`** to a new location in the memory.

    function ChangeObjectProp(o){
        o.prop1 = "changedProp";
    }
    ChangeObjectProp(objB);
    console.log(objB);//{ prop1: 'changedProp' }
    

Here the formal parameter to the function **`ChangeObjectProp`** holds the reference same as what **`objB`** holds. And because of this the original object got modified which again confirms that the object was passed by reference.

Now we have seen the Reference Specification type and how type conversions will behave in the world of JavaScript, we will move on to a core concept of Lexical Environment and Scope in our next post.