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).

Data types in Javascript

Introduction

Javascript is a loosely typed language which doesn’t mean it has no types. There are various Data Types in Javascript which a developer needs to be aware of for writing bug free code and also for easier debugging. By the end of this 5-10min reading you will get a quick overview of various Data types available in Javascript and how to identify them.

What does Loosely Typed mean?

Almost every programming language has a concept called variables which are nothing but containers to hold data of different types like integer, string etc. In traditional strongly typed programming languages like C, C++, Java etc the way you create these variables decide what type of data it is going to hold through out the program and if you try to assign data which is not the designated type the compiler throws an Error.

int i;              // variable that can hold only an integer
i = 10;             // Works fine
i = "John Doe";     // Compiler Error due to Strongly Typed nature

Now that we understand how a Strongly typed programming language works, let’s understand how a Loosely typed language like Javascript would work. Though there are many Data types in Javascript there is only one way to create variables to hold any type of Data like number, string etc using a var keyword as shown below

var i;              // variable that can contain any type of data
i = 10;             // Works fine
i = "John Doe";     // no error due to Loosely Typed nature of JS

Data Types in Javascript

Data types in Javascript are primarily divided into two types

  • Primitive Types
  • Reference/Object Types

See Primitive vs Reference types for a deeper insight.

Primitive Types

Javascript supports 5 primitive types which are listed below:

  1. Boolean (true/false)
  2. Number
  3. String
  4. Null
  5. Undefined

All primitive types can be identified using typeof operator except for null. typeof operator identifies null as an object which is an important Javascript quirk to be aware of. The best way to check if variable is null is by comparing it to null.

var name = "Techbuk";     // string
var age = 20;             // number
var isAdult = true;       // boolean
var email = null;         // null
var address = undefined;  // undefined

console.log(typeof name);    // prints "string"
console.log(typeof age);     // prints "number"
console.log(typeof isAdult); // prints "boolean"
console.log(typeof address); // prints "undefined"

console.log(typeof email)    // prints "object" ** JAVASCRIPT QUIRK **
console.log(email === null); // prints "true"

Reference Types

Javascript supports 6 reference types which are listed below:

  1. Array
  2. Date
  3. Function
  4. Object
  5. Regexp
  6. Error

All reference types can be identified using instanceof operator except for Arrays which might not be correctly identified in some cases. Hence it is recommended to use Array.isArray() to check for an Array as shown in the code example below:

var obj = {};              // Object
var arr = [1,2,3,4];       // Array
var date = new Date();     // Date
var fn = function() {};    // Function
var re = /Techbuk/i;       // RegExp
var err = new Error();     // Error

console.log(obj instanceof Object);   // prints true
console.log(date instanceof Date);    // prints true
console.log(fn instanceof Function);  // prints true
console.log(re instanceof RegExp);    // prints true
console.log(err instanceof Error);    // prints true

 ** JAVASCRIPT QUIRK **
console.log(instanceof arr) // might not work as expected in some cases
console.log(Array.isArray(arr)); // Do this instead
                                 // prints true

NOTE: typeof operator doesn’t work well with reference types hence it is recommended to use instanceof instead.

Conclusion

Though Javascript is a loosely typed language it supports 5 primitive types and 6 Reference types which are important to get comfortable with for any Javascript developer. Javascript typeof and instanceof operators can be leveraged to identify the types of variables.