JavaScript Types And Values, Explained

JavaScript Types And Values, Explained

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 index 1, 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:

  1. Number Type
  2. 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. 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. :::

Credit: mathiasbynens

 

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:

ConstructorNumeric type
Int8Array()signed bytes
Uint8Array()unsigned bytes
Uint8ClampedArray()unsigned bytes without rollover
Int16Array()signed 16-bit short integers
Uint16Arrayunsigned 16-bit short integers
Int32Arraysigned 32-bit integers
Uint32Array()unsigned 32-bit integers
BigInt64Arraysigned 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 the name 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 properties company_name and company_age.
  • Second, the company variable is assigned to the tech_company variable. The two variables now reference the same object in memory.

  • Finally, the tech_company variable changes the company_age property of the object on the memory heap from 25 to 30.

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