This article was initially published on the Open Replay Blog
Javascript is a dynamically typed language, which means variable types are identified at run time (done implicitly by the interpreter). As opposed to statically typed languages like Java and C++, where the developer has to explicitly define the type for each variable declared.
As a Javascript developer having a good understanding of types in Javascript, will give you a holistic view of the language and make you more confident as a Javascript developer.
INTRODUCTION
In a programming language values that can be represented and manipulated are known as types. Types are just labels given to data to enable the computer to make sense of it(at low-level computers see everything as data(1s and 0s)).
It is one of the core characteristics of any programming language to have a set of types it supports. There are basically two kinds of type in Javascript: primitive type and object type.
In this article readers will learn the following:
- The difference between a dynamic and static type language
- The difference between a type and a value in Javascript
- The primitive types and values
- The Object type
- Different Object properties
- Object property descriptor and attributes
- Built-in Javascript Objects
- The difference between Arrays and Typed Arrays (Indexed Collections)
- How primitive and reference values are copied
- How the Javascript Stack and heap memory works with primitive and reference values
TABLE OF CONTENTS
- STATIC VS DYNAMIC TYPE LANGUAGE
- TYPE VS VALUE
THE PRIMITIVE TYPES
- undefined
- null
- Booleans
- Strings
Numeric types
- Number
- Nan
- Big Int
Symbol
THE OBJECT TYPE
- Object Properties
- Object Property Descriptor And Attributes
- Built-in Objects
PRIMITIVE AND REFERENCE VALUES
- Stack And Heap Memory
- Copying Primitive Values
- Copying Reference Values
CONCLUSION
- Summary Of The Article
STATIC VS DYNAMIC TYPE LANGUAGE
An empty plastic container is used to store different types of items. Example— Liquid and Solid. When we decide to store only liquids in a container, that means we can't store a solid item in it right.
In a programming language, a variable is like an empty plastic container. In the sense that it is used to store different types of values.
In a statically typed language, the type of value that can be stored in a variable is explicitly defined by the developer. While in a dynamically typed language like Javascript type is implicitly set by the interpreter at run time.
TYPE VS VALUE IN JAVASCRIPT
According to the Javascript Specification:
An ECMAScript language type corresponds to values that are directly manipulated by an ECMAScript programmer using the ECMAScript language. The ECMAScript language types are Undefined, Null, Boolean, String, Symbol, Number, BigInt, and Object. An ECMAScript language value is a value that is characterized by an ECMAScript language type.
The preceding statement means that each Javascript type has a specific kind of value(s) it accepts. For example, different types of sports have their own specific rule(s). In the same way you can't score a basket(basketball rule) in soccer, a string
value can't be stored as a Number
type in Javascript.
THE PRIMITIVE TYPE
In Javascript, a Primitive type is a data type with an immutable value.
Javascript have the following primitive types(MDN):
- null
- undefined
- Booleans
- Strings
Numeric types
- Number
- BigInt
Symbols
:::info :information_source: The primitive types appear in Javascript as literal values. :::
2
4
6
8
10
true;
"good";
3.14;
null;
undefined;
:::info :information_source: Or as object instances of their Constructors :::
new Boolean(false); //object
new String("happy"); // object
new Number(22); // object
These object instances are rarely used.
null (MDN)
According to the Javascript Specification:
null
is a primitive value that represents the intentional absence of any object value
null is a Javascript keyword that is normally used to indicate the absence of a value. null is regarded as the only member of its type(Null type), and it can be used to indicate "no value" for strings and numbers as well as objects.
When the typeof
operator is used on null, the string "object" is returned.
:::info
:information_source: This was actually a mistake in the early Javascript implementation. It is advisable to use the strict operator ===
instead of typeof
when type checking a null value.
:::
This means that null can also be regarded as a special object value that indicates "no object".
For example:
let greetingObject = {
english: 'hello',
french: 'bonjour'
}
let greetingObject = null; //no object
In the preceding code, the greetingObject
variable is assigned a null value after it was initially assigned to an object. The null value means that an object is expected to be assigned to a variable, but for some reason, it's not assigned. This is also the case when a function
returns a null value.
undefined (MDN)
The undefined is used to indicate the absence of a value in JavaScript just like null
.
An undefined value is returned:
- When a variable has not been initialized.
- When you try to access an object property or array element that does not exist.
- When functions don't explicitly return a value.
- When a value is not passed to a function parameter by an argument, the value of the parameter becomes undefined.
The undefined value is the sole member of the Undefined type.
:::info
:information_source: The equality operator ==
considers undefined
and null
to be equal.
null == undefined; // => true
Use the strict equality operator ===
to distinguish them.
null === undefined; // => false
:::
Boolean (MDN)
According to the Javascript Specification:
The Boolean type represents a logical entity having two values, called true and false.
Booleans are simply the true
and false
values in JavaScript.
JavaScript can also implicitly convert other types of values into booleans(truthy and falsy values).
Learn more about the Boolean type here.
Strings (MDN)
The String type is used to represent text in Javascript. However, a string value is an immutable sequence of 16-bit values, each of which represents a Unicode character.
:::info :information_source: 16 bit value = 2^16^ (or 65,536) distinct values
:::
Important things to know about strings:
- Javascript strings(and arrays) use zero-based indexing: the first 16-bit value is at index
0
, the next index1
, and so on. - The length of a string is the number of 16-bit values it contains.
- In ES6+ strings are iterable, a
loop
can be used on a string.
Learn more about Strings here.
Numeric Types(MDN)
Numeric types are used to represent numbers in Javascript.
There are two Numeric Types in Javascript:
- Number Type
- BigInt Type
Number Type
This is Javascript's primary numeric type. A number value can be in the form of an integer(20
) or a floating-point number (21.5
).NaN
andInfinity
are also considered to be number values in Javascript. TheNaN
(Not a Number) value is technically a non-numeric value a statement can evaluate to. However, theInfinity
value represents the mathematical infinity(something larger than the natural number), they are both global constants(properties of the global object. e.g thewindow
object in the browser).
Learn more about the Number type here.
BigInt Type
The BigInt Type was added in ECMAScript10(ES10), it is a numeric type whose values are integers. It was included in JavaScript mainly to allow the representation of 64-bit integers, which are required for compatibility with other programming languages and APIs.
Before ES10 the maximum number value created in Javascript used either the number literal or the Number()
constructor and was stored in the Number.MAX SAFE INTEGER
which is equal to 9007199254740991
. However, with the BigInt type, we can specify numbers greater than Number.MAX SAFE INTEGER
. This means BigInt values can have thousands or even millions of digits.
A BigInt
value can be created by using the BigInt(number)
function or appending n
to the end of an integer value.
Example:
const bound_number = Number.MAX SAFE INTEGER;
const unbound_number = BigInt(Number.MAX SAFE INTEGER);
const big_number = 9007199254740991n;
Learn more about BigInt here.
Symbols (MDN)
The Symbol is a unique and immutable data type introduced in ECMAScript6(ES6) to serve as a non-string property name for objects. Before ES6 property names of objects in Javascript could only be strings, but with the Symbol type, we can specify property names as Symbols too.
:::info
:information_source: Symbols are not enumerable, that's the reason it can't be accessed using the Object.keys()
method on an object that uses it as a key.
:::
Creating Symbols:
Global Symbol()
function.
let first_name = Symbol();
let person = {};
person[first_name] = "John";
console.log(person[first_name]) // "John"
In the preceding code a symbol first_name
is created using the Symbol()
function and used to assign a new property to the person
object.
The Symbol function also accepts an optional argument that is a description of the symbol. However, the description can't be used to access the property, it is a good practice to always provide a description to make reading and debugging easier.
let first_name = Symbol("first name");
let person = {};
person[first_name] = "John";
console.log("first name" in person) // False
console.log(person[first_name]) // "John"
console.log(first_name) // "Symbol(first name)"
Symbols are always unique:
Every Symbol is unique, two symbols can never be equal to each other.
let first_symbol = Symbol("symbol_1");
let second_symbol = Symbol("symbol_1")
console.log(first_symbol === second_symbol); // False
In the preceding code, two identical Symbols first_symbol
and second_symbol
are created, even with the same descriptions they are both unique and different.
Learn more about Symbols here.
THE OBJECT TYPE
According to the JavaScript Specification
An Object is logically a collection of properties.
An Object can be seen as a composite value, made up of multiple values(primitive values and other objects), and allows you to store and retrieve values by name. The values collected by an object are known as properties.
Object Properties
The property(property value) of an object is the core part of any object, it is made up of a name(key) and a value. Property names are usually strings(they can also be Symbols) mapped to a value.
Types of Object Properties
There are two types of object properties: The data property and the accessor property.
Data Properties
When an object is written like this —
const data_object = {
job: 'writer',
id: 4
}
data_object.job
// 'writer'
In the preceding code, the job
and id
properties of the data_object
object are called Data Properties. This is the default way of creating object properties in JavaScript(As you have seen in most Javascript code).
Accessor Properties
An accessor property is an aggregate of two functions: the get
and the set
function. It associates a property name(key) with each of two accessor functions(get
and set
) to fetch or store a value.
Example
const accessor_object = {
get job() {
return 'writer'
}
};
accessor_object.job; // 'writer'
const data_object = {
job: 'writer',
};
data_object.job // 'writer'
In the preceding code, the job
property is created and retrieved from both the accessor_object
and data_object
. However, the syntax used to create the job
property in the accessor_object
object is different. The get
keyword is used followed by a function declaration with the property name(i.e job
) that returns the property value('writer'
).
:::info :information_source: The syntax for retrieving accessor properties and data properties are the same, notwithstanding how the properties are created.
accessor_object.job; // 'writer'
data_object.job // 'writer'
:::
The get
function is called a getter since it is used to get the value of an object property. if the accessor_object
is updated like this accessor_object.job = 'developer'
, the update won't work. This is because we need a corresponding setter function for the job
property. Setter functions are used to set values in an accessor object.
const accessor_object = {
job: 'writer',
get name() {
return this.name;
},
set job(value) {
this.job = value;
}
};
accessor_object.job = 'developer';
// update works because of the setter function
In the preceding code, the accessor_object
now has both getter
and setter
functions. The job
property value can now be updated because of the setter function.
Object Property Descriptor And Attributes
An object property descriptor is a composite value: It aggregates multiple values known as property attributes, that define the meta-data of the value associated with a key in an object. It simply defines what the value of an object property will look like via the following property attributes.
- [[Value]]
- [[Get]]
- [[Set]]
- [[Writable]]
- [[Enumerable]]
- [[Configurable]]
:::info
:information_source: The[[double square brackets]]
notation is used because they are internal properties. Internal properties are properties used by the ECMAScript specifications(meaning they are not directly exposed like most properties). To modify internal properties we use special methods provided by Javascript.
:::
In the preceding diagram, the property descriptor of the object
is shown containing various property attributes of x
and y
(object
properties).
Learn more about property descriptors and attributes here.
Built-In Objects(MDN)
You should have an idea of what they are from the name' built-in' objects. Built-in Objects are simply objects that come with Javascript by default, which enables you to implement various functionalities in your application.
There are various built-in objects(check here) but in this article, we will look at the following:
- Fundamental Objects
- Numbers and Dates
- Text Processing
- Indexed Collection
- Keyed Collection
Fundadmental Objects
As defined by MDN
These are the fundamental, basic objects upon which all other objects are based. This includes general objects, booleans, functions, and symbols.
Example: When you create a "normal object".
object = {
x: 3,
y: 5
}
Numbers and Dates
These are the base objects representing numbers, dates, and mathematical calculations. - MDN
- Number
- BigInt
- Math
- Date
Let's look at the Math Object: The Math
Object allows us to carry out mathematical operations in Javascript, through its various methods and properties.
For example, if we want to find the square root of a number we will use Math.sqrt(x)
method.
const number_value = 9;
const square_root = Math.sqrt(number_value)
console.log(square_root) // 3
Text Processing
These objects represent strings and support manipulating them. - MDN
- String
- RegExp
Indexed Collections: Arrays and Typed Arrays
Arrays are normal objects with integer-keyed properties. It is an ordered collection of values. Each value is known as an element, and each element has a numeric position in the array, known as its index. It also has a length
property that can be used to retrieve the number of elements contained in an array.
Example:
const names = ['John', 'Mary'];
console.log(names.length) // 2
Typed Arrays were introduced in ES6, primarily designed to work with numeric types. Typed arrays are technically not arrays(Array.isArray()
returns false
for them), but normal array methods can be used on them.
The difference between Typed arrays and Arrays are:
- The elements of a typed array are all numbers. Not the regular Javascript numbers(which use the 64-bit double-precision format), In typed arrays, you can specify your preferred number type(signed and unsigned integers and IEEE-754 floating-point number) and its size(8 bits to 64 bits) that you want to store in the array.
- Typed arrays have a fixed length, the length can only be specified when it's been created and can't be changed.
- The elements of typed arrays are always initialized to
0
when the array is created.
The following 11 Numeric types can be stored and manipulated in a Typed Array:
Constructor | Numeric type |
Int8Array() | signed bytes |
Uint8Array() | unsigned bytes |
Uint8ClampedArray() | unsigned bytes without rollover |
Int16Array() | signed 16-bit short integers |
Uint16Array | unsigned 16-bit short integers |
Int32Array | signed 32-bit integers |
Uint32Array() | unsigned 32-bit integers |
BigInt64Array | signed 64-bit BigInt values (ES2020) |
BigUint64Array() | unsigned 64-bit BigInt value (ES2020) |
Float32Array() | 32-bit floating-point value |
Float64Array() | 64-bit floating-point value: regular Javascript number |
Keyed Collections:
These objects represent collections which use keys. The iterable collections (Map and Set) contain elements which are easily iterated in the order of insertion. -MDN
- Map
- Set
- WeakMap
- WeakSet
PRIMITIVE AND REFERENCE VALUES
When a variable is assigned a value of the Javascript Primitive Type, the variable is said to contain a primitive value. However, if an Object(normal objects, arrays, and functions) is assigned as a value to a variable, the variable is said to contain the reference value of the Object.
The Javascript engine stores both values differently in memory—hence the stack and the heap.
Stack And Heap Memory
The stack and heap are basically the two memory locations, where variables are stored when they are declared in JavaScript. We will use the stack and the heap to understand primitive and reference values better, especially how they are stored as static and dynamic data on the stack and heap respectively.
Due to performance reasons primitive values and reference values are stored as static data(data whose size is fixed) on the stack. In contrast, Objects are stored as dynamic data on the heap(the object reference value is stored on the stack) because of the memory flexibility of the heap.
For Example
let company_name = 'Netflix';
let company_age = 24;
In the preceding code, because the string
and number
primitive values are stored in the variables company_name
and company_age
. The variables will be stored on the stack by Javascript.
Now let's create an object that will be stored on the heap.
let company_name = 'Netflix';
let company_age = 24;
let company = {
company_name: 'Netflix',
company_age: 25
};
In the preceding diagram, Javascript assigns memory on the stack for three variables company_name
, company_age
, and company
. A new object is also created in the heap memory that is linked to the company
variable on the stack. Because of the link between the company
variable and the object on the heap memory, we say that the company
variable stores the reference value of the object on the heap memory.
Copying primitive values
When a primitive value is assigned from one variable to another using the =
operator, the value is said to be copied to the new variable.
Example
let name = 'John';
let new_name = name;
In the preceding code:
- A new variable
name
is declared and initialized with a value of'John'
. - Next, the
new_name
variable is declared and assigned thename
variable as its value.
Under the hood, Javascript creates a copy of the primitive value 'John'
and assigns it to the new_name
variable.
Copying reference values
When a reference value of an object is assigned from one variable to another. The variables the reference value is assigned to will refer to the same object on the heap memory. This means changes made to one variable will affect the other.
Example:
let company {
company_name: 'Netflix',
company_age: 25;
};
let tech_company = company;
tech_company.age = 30;
In the preceding code:
- First, a
company
variable is declared and initialized with an object with two propertiescompany_name
andcompany_age
. - Second, the
company
variable is assigned to thetech_company
variable. The two variables now reference the same object in memory.
- Finally, the
tech_company
variable changes thecompany_age
property of the object on the memory heap from25
to30
.
As you know by now, the company
and tech_company
variables reference the same object, so changes made to the object via the tech_company
variable is also reflected in the company
variable.
CONCLUSION
Now you know about the types and their various values in Javascript, you will be more aware of how you use the various types and values when using Javascript.
Summary
In this article you learned the following:
- The difference between a dynamic and static type language
- The difference between a type and a value in Javascript
- The primitive types and values
- The Object type
- Different Object properties
- Object property descriptor and attributes
- Built-in Javascript Objects
- The difference between Arrays and Typed Arrays (Indexed Collections)
- How primitive and reference values are copied
- How the Javascript Stack and heap memory works with primitive and reference values