Javascript reference types in depth

Introduction

In my previous posts we have looked into various datatypes and also the difference between primitive and reference types in javascript. In this post let’s take a much closer look at the reference types in javascript and learn some interesting facts about them.

Reference Types

As explained in my earlier post the following are some of the major reference types supported by javascript

  • Array
  • Date
  • Function
  • Object
  • RegExp
  • Error

Instantiating using new operator vs Literal forms

All the above types can be instantiated using new operator but javascript also provides a much convenient literal form for most of these types to create their instances. The literal form is very common and so widely used that sometimes we forget the fact that all these reference types can be instantiated using new operator. Let’s look at an example of creating these objects using literal form as well as using a new operator.

// array literal form
let arr1 = [];
// instantiating Array reference type
let arr2 = new Array();

// function literal form
function printHello1() {
    console.log("hello");
}
// instantiating Function reference type
let printHello2 = new Function("console.log('hello');");

// object literal form
let obj1 = {};
// instantiating Object reference type
let obj2 = new Object();

// regexp literal form
let reg1 = /\d+/g
// instantiating RegExp reference type
let reg2 = new RegExp('\\d+', 'g');



NOTE 1: Though it is recommended to use literal forms over instantiating using new operator it is still important to be aware of the fact that these can be instantiated using new operator.

NOTE 2: The outcome of creating these instances using literal form or using new operator is very much the same.

Some interesting facts about Reference Types

  • All reference types in Javascript are objects, we can confirm the same using the following code:
console.log(Array instanceof Object);    // prints true
console.log(Date instanceof Object);     // prints true
console.log(Function instanceof Object); // prints true
console.log(Object instanceof Object);   // prints true
console.log(RegExp instanceof Object);   // prints true
console.log(Error instanceof Object);    // prints true
  • All reference types in Javascript are also functions, we can confirm the same using the following code:
console.log(typeof Array);    // prints "function"
console.log(typeof Date);     // prints "function"
console.log(typeof Function); // prints "function"
console.log(typeof Object);   // prints "function"
console.log(typeof RegExp);   // prints "function"
console.log(typeof Error);    // prints "function"

// lets make sure using instanceof
console.log(Array instanceof Function);    // prints true
console.log(Date instanceof Function);     // prints true
console.log(Function instanceof Function); // prints true
console.log(Object instanceof Function);   // prints true
console.log(RegExp instanceof Function);   // prints true
console.log(Error instanceof Function);    // prints true
  • I would like to point out another interesting fact about these types in case you missed to notice is Object and Function are instances of themselves where as no other reference type is instance of itself. Lets confirm the same through code
console.log(Object instanceof Object);     // prints true
console.log(Function instanceof Function); // prints true

console.log(Array instanceof Array);       // prints false
console.log(Date instanceof Date);         // prints false
console.log(RegExp instanceof RegExp);     // prints false
console.log(Error instanceof Error);       // prints false

Yes, in javascript objects and functions are special and requires a deeper understanding to master Object Oriented Javascript.

So far we have seen some interesting and also a bit confusing facts about javascript types so its better to take a moment and digest them.

  • Now we know that all the reference types are function objects but they are invoked with new operator unlike regular functions and hence they are referred as constructor function objects.

NOTE: Since all functions in javascript are also objects the constructor functions objects are usually referred as constructor functions or simply constructors.

Conclusion

All the reference types in javascript are nothing but constructor functions which can be invoked using new operator to create their instances. A good grasp of reference types will help in understanding other advanced concepts like custom reference types using constructor functions etc.

Primitive vs Reference/Object Types in Javascript

Introduction

In my previous post I explained about data types in javascript which briefly introduces you to two categories of data types i.e primitive and reference/object data types. In this post I will try to explain more on differences between primitive and reference data types.

Primitive Types

  • The variables that are assigned primitive type data such as number, string etc holds the actual value but not the address (like reference types).
  • The primitive values are typically stored in stack memory.
  • Variables holding primitive values when assigned to a new variable,  a new copy of that value is assigned.
  • Also see data types in javascript for various primitive data types available in javascript.

Example 1:

var name = "techbuk";
var newName = name;  // a new copy is created and assigned
// --- see memory state 1 in the image below
console.log(name);      // prints "techbuk"
console.log(newName);   // prints "techbuk"

newName = "blah";       // name is unchanged
// --- see memory state 2 in the image below

console.log(name);      // prints "techbuk"
console.log(newName);   // prints "blah"
primitive type – memory state
  • Primitive values follow call by value a.k.a pass by value which means when a primitive value is passed as an argument to a function, the receiver function creates a new variable with the same value passed and hence any changes to that value inside the function won’t affect the actual variable (outside the function)

Example 2:

var name = "John";

function appendLastName(name) {  // a local copy of name is created
    name = name + " Doe";
    console.log(name);  // prints "John Doe"
}

console.log(name);      // prints "John"
appendLastName(name);   // passing value
console.log(name);      // still prints "John"

Reference/Object Types

  • The variables that are assigned reference type data such as an object, array etc holds a reference(address) to the object but not the actual value (like primitives) .
  • The objects are typically stored in the heap memory which have references stored in variables on the stack.
  • Hence these variables can be considered as pointers to objects stored on the heap. When these variables are assigned to a new variable the new variables also start pointing to the same instance in the heap memory.
  • Also see data types in javascript for various reference date types available in javascript.

Example 3:

var nameObj = { name: "techbuk" };
var newNameObj;
// --- see memory state 1 in the image below

newNameObj = nameObj;  // assigns the same address that nameObj is pointing to
// --- see memory state 2 in the image below

newNameObj.name = "blah";
// --- see memory state 3 in the image below
console.log(nameObj.name);  //prints "blah"
console.log(newNameObj.name);  //prints "blah"

reference type – memory state

 

  • Reference types follow call by reference a.k.a pass by reference which means when a reference type is passed as an argument to a function, the receiver function creates a new variable with the same reference or address passed and hence any changes to that object inside the function will affect the actual variable (outside the function)

Example 4:

var nameObj = {name: "John"};

function appendLastName(obj) { // obj is reference to original nameObj
    obj.name = obj.name + " Doe";
}

console.log(nameObj.name);    // prints "John"
appendLastName(nameObj);      // passing reference
console.log(nameObj.name);    // prints "John Doe"

Example 5: ( A more complex scenario of a nested object)

var addrObj = {
    street:  "12 market street",
    city: "San Francisco",
    zip: "94101"
}
var userObj = {
     name: "techbuk",
     age: 20,
     address: addrObj  // object property is another object
};
// --- see the image below for memory representation
reference type – memory state

Conclusion

It is important for any javascript developer to understand in depth the difference between primitive and reference data types. To summarize the it in brief primitive types are stored and passed between functions as values where as reference types are stored and passed as references (addresses).