JavaScript Types and Values, explained
Javascript is a dynamically typed language, which means variable types are identified at run time (done implicitly by the interpreter), unlike statically typed languages (like Java and C++) in which the developer has to explicitly define the type for each variable declared.
As a Javascript developer, having a good understanding of types 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 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 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
STATIC VS DYNAMIC TYPE LANGUAGE
In a programming language, a variable is like an empty 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. In a dynamically typed language like Javascript, the 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 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 and BigInt)
- Symbols
Primitive types appear in Javascript as literal values.
2
4
6
8
10
true;
"good";
3.14;
null;
undefined;
or as object instances of their Constructors — though these object instances are rarely used.
new Boolean (false); //object
new String ("happy"); // object
new Number (22); // object
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 customarily 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. 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.
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 it’s not assigned for some reason. 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, the parameter’s value becomes undefined.
The undefined value is the sole member of the Undefined type.
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 JavaScript’s true
and false
values.
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.
Important things to know about strings:
- Javascript strings (and arrays) use zero-based indexing: the first 16-bit value is at index
0
, the following 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
and Infinity
are also considered to be number values in Javascript. The NaN
(Not a Number) value is technically a non-numeric value a statement can evaluate to. However, the Infinity
value represents the mathematical infinity (something larger than the natural number). They are both global constants (properties of the global object. e.g., the window
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
. 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 also specify property names as Symbols.
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, and 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.
Open Source Session Replay
OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.
Start enjoying your debugging experience - start using OpenReplay for free.
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
An object’s property (property value) is the core part of any object, and 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 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 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 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 followed by a function declaration with the property name (i.e. job
) that returns the property value (“writer”).
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 setter function can now update the job
property value.
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]]
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
contains various property attributes of x
and y' (
object` properties).
Learn more about property descriptors and attributes here.
Built-In Objects (MDN)
You should know 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 a number’s square root, we will use the 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: String and RegExp.
Indexed Collections: Arrays and Typed Arrays
Arrays are ordinary 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. An array 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, but 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 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:
According to MDN:
These objects represent collections which use keys. The iterable collections (Map and Set) contain elements which are easily iterated in the order of insertion.
-
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 values differently in memory—the stack and the heap.
Stack And Heap Memory
The stack and heap are the two memory locations where variables are stored when they are declared in JavaScript. We will use the stack and the heap to better understand primitive and reference values, 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 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 thename
variable is assigned 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, both variables 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 properties,company_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