What are data types?

Computer programs usually deal with a lot of data. That data can be of several types such as integers, floats, strings, Booleans and so on. Each type has its own purposes, functionalities and underlying mechanism of implementation.

Some are atomic i.e simplest they can get, like numbers, whereas some are compound i.e a collection of atomic types, like an array of numbers.

In this chapter we shall get a very general overview of the data types JavaScript comes equipped with, along with some other details including the typeof operator that allows us to get the data type of a given value.

This understanding is imperative for you to be able to digest some additional concepts in this unit, before moving on to explore the data types in a lot more fine detail. So let's get straight into it.

Primitives and Objects

JavaScript distinguishes data essentially into two main categories - primitives and objects.

Let's start by defining what a primitive it:

A primitive is a value without any properties or methods attached to it.

Simply put, a primitive value is just the atomic value we were talking about previously. It depicts the lowest-level implementation of a piece of data.

JavaScript comes with five primitive data types: numbers, strings, Booleans, undefined and null.

On the other hand, an object is the mirror image of a primitive:

An object is a value with properties and methods attached to it.

Simply put, if a value isn't a primitive it is an object. An object is a compound value i.e a mixture of primitives and objects.

JavaScript comes with the following object types: arrays, functions (a callable object) and pure objects.

The most interesting distinction between primitives and objects is that the former is passed by value, while the latter is passed by reference. Primitives are copied and then passed over to variables; whereas objects aren't copied themselves, but rather their references are.

You'll learn more on passing by value vs. passing by reference in the Values and References chapter.

Primitive data types

Let's start by taking a look over the primitives in JavaScript.

Numbers

Not surprisingly, first in the list we have numbers.

Numbers are everywhere when it comes to computing - they are used in arithmetic, math, graphical calculations, transformations, algorithms, and much more..

Generally numbers are categorised into two groups - integers and floats.

An integer, as we know, is a whole number without a decimal point. Examples include 0, 1, 100, -30. Similarly, a float is a fractional number with a decimal point. Example include 0.1, 3.878, -4589.4 and so on.

Some programming languages actually make this distinction between numbers by providing individual types int and float. However, JavaScript doesn't make any distinction between integers or floats - we've got only one type of numbers in the language and that is "number".

Consider the following code:

var num1 = 10; // An integer
var num2 = 10.5; // A float

console.log(num1 + num2); // adding numbers

console.log(10 - 20); // subtracting numbers

Here we use the number literal to create a number in JavaScript. What is a literal?

A literal is any non-constructor way of creating a data type

You'll understand this term better as you read across this chapter.

We will go over numbers in detail in the Numbers unit.

Strings

Another extremely common data type in JavaScript, and nearly all programming languages, is the string type.

Strings are, simply, textual values in programming. They can contain characters, symbols, spaces, newlines, emoticons etc.

They are denoted by a pair of single quotes '', double quotes "", or a pair of backticks ``. The first two are fairly similar, while the last one is a special feature of JavaScript known as template literals.

We'll learn more about template literals in the Strings Basic Concepts chapter.

The following code all show examples of strings.

var str1 = "Hello"; // double quotes
var str2 = 'Hello'; // single quotes
var str3 = `Hello`; // backticks

Booleans

The third in this list is Booleans.

Booleans are simply true or false values. They are used extensively in conditional programming to control program flow by making decisions on the outcomes of given evaluations.

The following code creates two Boolean variables:

var proceed = true;
var stopNow = false;
We will go over Booleans and their applications in detail in the JavaScript Booleans chapter.

Object data types

Arrays

The first data type in the object category is arrays.

An array is an ordered collection of data stored at contiguous indexes. An array has the capability of storing multiple values under one hood - we refer to the individual data blocks of an array as elements.

An array can be created very conveniently using array literals i.e pair of square brackets []. Individual elements go within the brackets and are separated using commas ,.

The following code shows an array arr created using literal notation:

var countries = ["Australia", "Austria", "Netherlands", "China"];

There's yet another way to create arrays, in fact - values of any data type, known as constructors. Following we demonstrate the constructor way to create an array.

The new keyword is used to create objects out of a constructor.

var countries = new Array("Australia", "Austria", "Netherlands", "China"); // An array object created using the Array constructor

Javascript provides constructor functions for all data types except for undefined and null - Number() for numbers, String() for strings, Boolean() for booleans and so on.

What's the purpose of these constructors?

A novice developer always raises this question that what's the use of these constructor functions?

Well, when we create numbers, strings or Booleans in JavaScript using their literal representations we are creating the values as-is in memory i.e they have no attached properties and methods on them.

This idea works well until and unless we need to process the values.

Now the moment we do need to process these values, such as converting a string to uppercase characters, the JavaScript engine has to obtain an object out of these simple values - which has the desired properties and methods to perform the respective processes.

A string value will hence be converted to String, the function performed on it, and finally the result returned back. This promotes memory efficiency - we're not creating big objects all the time to represent simple data types such as numbers, strings, Booleans.

It's only when the need is, that we box the simple data types into their corresponding object types using their corresponding constructors.

At this stage you don't need to know much about constructors except for that wherever you see the new keyword you are dealing with a constructor.

Objects

The second is objects. Objects are values that can contain properties and methods. Properties can contain any of these data types as their values and methods are properties that contain a function definition as their value.

If this sounds a bit complex to you, don't worry. We will explain the above mentioned definitions in detail in our Ojects unit.

The following code shows examples of objects:

var phone = { name: "Samsung Note 8", os: "Android", left: 50, price: "High Range", osDesc: function () { return this.name + " has the os " + this.os } };

console.log(typeof phone); // object
console.log(phone.name); // Samsung Note 8
console.log(phone.os); // Android
console.log(phone.left); // 50
console.log(phone.price); // High Ranged
console.log(phone.osDesc()); // Samsung Note 8 has the os Android
To discover more on objects head over to the Objects unit.

Functions

And the last in this list is functions. Function are containers of a whole block of code that can be called for execution. Functions can allow code to be gathered under one name, one purpose and executed only at calls.

The following code shows examples of functions:

function welcome() {
    console.log("Hello Programmer!");
}

welcome(); // Hello Programmer!
To discover more on functions head over to the Functions unit.

The typeof operator

Uptil now we've only been creating variables of given data types, without discovering any way to programatically retrieve the type of those variables.

Now we shall address this very idea and understand the typeof operator.

The typeof operator returns the data type of a given expression, as a string value. The expression follows the operator as shown below:

typeof expression

Following we test it on different values to see what it returns in each case:

typeof 10; // "number"
typeof 3.142; // "number"

typeof "Hello"; // "string"
typeof 'Hello'; // "string"

typeof true; // "boolean"

typeof undefine; // "undefined"

As you can clearly see here, for all the first four primitive types, typeof returns exactly the same names as of the primitive data types in JavaScript.

We have "number" for numbers, "string" for strings, "boolean" for booleans and "undefined" for undefined.

Now you might be wondering that we forgot about null.

Well, we didn't! It's just how typeof treats a null value that we've considered to put a separate discussion on it.

So let's witness the surprise of null as inspected by typeof:

typeof null; // "object"

This statement returns a value that has proven to be one of the most confusing aspects of JavaScript for newbie developers.

How is null an "object"?

What, null is an object? How come?

Well, typeof returning "object" on the null value is an official bug in JavaScript introduced by its previous implementations.

Unfortunately, it can't be rectified because probably many programs have already utilised this behaviour in their programs - likewise it's present to date simply for backwards compatibility.

Nonetheless one could try to make some intuition by thinking that null represents an empty pointer, and when we talk about pointers we know we are dealing with objects.

If this makes sense or not, that's upto your reasoning about it; it's regardless an inherited bug in JavaScript from previous implementations and doesn't need to make sense, if at all!

Moving on, let's now dive into exploring typeof as used on object data types.

Surprises don't just end at null's typeof behaviour - the operator also returns some unexpected results when used on arrays.

Following is an illustration:

typeof [1, 2, 3]; // "object"

For array objects, typeof simply returns "object"; and NOT the much expected value "array".

Fortunately, unlike "object" for null values, this has got some sense to it and is definitely not another bug!

How is an array an "object"?

As we know, arrays fall in the object category of JavaScript data types i.e they are stored by references and NOT by their actual values.

JavaScript simplifies the work of typeof by returning "object" whenever the expression is a reference to some data in memory.

As such, an array is indeed a reference to an ordered bunch of data in memory and likewise translates to "object" when inspected by the typeof operator.

This makes perfect sense - everything in the language, except for the primitive types, is an object and hence should return "object" when inspected by typeof.

The only exception to this is the function data type, where typeof returns "function". We'll see more details below.

As you may see later in this course, regular expressions in their literal form also translate to "object" with typeof.

But now you might be thinking that how can we figure out whether a given value is an array or not?

Keep calm! JavaScript surely has methods available to solve this problem of detecting pure arrays and they will be discussed, in detail, in the Arrays Basic Concepts chapter.

Extending to this discussion, if we have pure objects then, as we expect and have already detailed above, typeof will return "object" once again.

typeof {}; // "object"
typeof {x: 10}; // "object"

To end the discussion let's finally see what happens when we are working with functions.

The type returned by typeof for functional values is "function", as can be seen in the following example:

typeof function() {}; // "function"

OK, so now we've another thing to deal with! Functions are an exception case to reference types when evaluated by typeof.

How is a function not an "object"?

The reason why typeof returns "function" for functions is described as follows:

It's fairly easy to check for a functional value as compared to any other reference type - only an internal property [[Call]] needs to be searched for and if its exists we know we are dealing with a function.

Even if someone would argue that it isn't difficult to check for arrays as well, just like it isn't difficult to check for functions; there still is a good reason to return "function" for functions.

The whole idea is that functions are special kinds of objects in JavaScript - they are callable objects.

Because of this distinction from all other objects, it makes a lot of sense to treat them a bit differently - special from all others!

To sum it all up, what you should remember is that whenever a given value is not a primitive and not a function typeof will return "object" as its data type.

Javascript is loosely typed

If you've ever done programming before in languages like Java, C++ etc, you would've surely noticed one difference in variable typing in those languages and JavaScript.

Consider the following code snippet from a Java program:

public class Example {
    public static void main(String args[]) {
        // declare num as an integer
        int num = 10;

        // change num to a Boolean value
        num = true; // throws an error
    }
}

This code would throw an error since the variable num, that is initialised to be an integer, is being changed to a Boolean. Since Java is a strictly-typed language it doesn't allow assigning a value to a variable that doesn't match with its data type.

The same is NOT the case with JavaScript.

In Javascript, we can easily change the data type of a variable after it has been assigned a value, and the interpreter won't throw an error.

This behaviour of the language is why it is termed as being loosely typed.

In contrast to a strictly-typed language, a loosely-typed language allows variables to change their data types, without raising errors.

Consider the code below:

// x is a number
var x = 10;

// x is now a string
x = "Hello";

// x is now a Boolean
x = false;

First we assign a number value to the variable x, but then afterwards change it to a string and then finally to a Boolean. This is possible only because the language doesn't constrict variables with the data types they have been initialised with.

This also explains the fact as to why there aren't any declaration keywords in JavaScript like int, float, double to declare variables of specific data types - the language doesn't need them and can automatically handle the type changes.