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:
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:
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.
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?
You'll understand this term better as you read across this chapter.
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.
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;
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.
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
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!
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?
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.
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.
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.
"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:
[[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.
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.