Skip to main content

Command Palette

Search for a command to run...

All you need to know about Data Types in JavaScript

Updated
7 min read

JavaScript is one of the most popular programming languages, powering the web and beyond. A fundamental aspect of JavaScript is its data types, which define the kind of data you can work with and how you can manipulate it. Whether you're a beginner or a seasoned developer, understanding data types is crucial for writing efficient and bug-free code. In this blog, we’ll explore everything you need to know about data types in JavaScript, from the basics to advanced concepts.

Introduction to Data Types in JavaScript

Data types are the building blocks of any programming language. They define the type of data a variable can hold, such as numbers, strings, or objects. In JavaScript, data types are categorized into two main groups:

  • Primitive Data Types: Simple, immutable values like string, number, boolean, etc.

  • Non-Primitive Data Types: Complex, mutable values like object, array, and function.

Primitive vs. Non-Primitive Data Types

Primitive Data Types

Primitive data types are immutable (cannot be changed after creation) and are stored by value. JavaScript has 7 primitive data types:

  • string: Textual data (e.g., “Hello”)

  • number: Numeric data (e.g., 23, 3.14)

  • bigint: Large integers (e.g., 9999999999999999n)

  • boolean: Logical values (true or false)

  • undefined: A variable that has been declared but not assigned a value

  • null: Represents an intentional absence of any object value

  • symbol: A unique and immutable value used as an identifier

Example:

let name = "John"; // string
let age = 23; // number
let isMarried = false; // boolean
let bigNumber = BigInt(9999999999999999); // bigint
let unknown; // undefined
let empty = null; // null
let id = Symbol("id"); // symbol

Non-Primitive Data Types

Non-Primitive data types are mutable and stored by reference. They include:

  • object: A collection of key-value pairs

  • array: A list of values

  • function: A reusable block of code

Example:

let person = { name: "John", age: 23 }; // object
let colors = ["red", "green", "blue"]; // array
function greet() { console.log("Hello!"); } // function

Dynamic and Weakly typed Nature of JavaScript

JavaScript is a dynamically typed language, meaning you don’t need to declare the type of a variable explicitly. The same variable can hold different types of data at different times.

Example:

let anything;
console.log(typeof anything); // Output: "undefined"

anything = 23;
console.log(typeof anything); // Output: "number"

anything = "JavaScript";
console.log(typeof anything); // Output: "string"

JavaScript is known for being a weakly-typed language, which means that it permits implicit type conversion in situations where different types are used in an operation, rather than generating type errors.

Example:

let first = 1;
let second = first + "2"; // Number is coerced into a string
console.log(second); // Output: "12"
console.log(typeof second); // Output: "string"

Deep Dive into null and undefined

  • undefined: A variable that has been declered but not assigned a value

  • null: Represents an intentional absence of any object value

Example:

let unknown;
console.log(unknown); // Output: undefined

let empty = null;
console.log(empty); // Output: null
💡
Interestingly, typeof null returns “object” due to a historical bug in JavaScript.

Type Coercion and Common Pitfalls

Type coercion is the automatic conversion of values from one type to another. While it can be convenient, it can also lead to unexpected results.

Example:

console.log(1 == "1"); // Output: true (type coercion)
console.log(1 === "1"); // Output: false (strict equality)

Common pitfalls include:

  • Using == instead of ===

  • Unexpected results with NaN (e.g., NaN===NaN returns false)

Working with BigInt

BigInt is used to represent integers larger than the Number type can handle.

Example:

const bigNumber = BigInt(9999999999999999999);
console.log(bigNumber); // Output: 9999999999999999999n

Symbols and Their Use Cases

Symbol is a unique and immutable primitive value, often used as an identifier for object properties.

Example:

const id = Symbol("id");
const user = {
    name: "John",
    [id]: 123
};
console.log(user[id]); // Output: 123

Checking Array and Object Types

Since typeof returns “object” for arrays and objects, use Array.isArray() or instanceof to differentiate.

Example:

const arr = [1, 2, 3];
const obj = { name: "John" };

console.log(Array.isArray(arr)); // Output: true
console.log(arr instanceof Array); // Output: true
console.log(obj instanceof Object); // Output: true

Functions as First-Class Citizens

In JavaScript, functions are objects and can be assigned to variables, passed as arguments, or returned from other functions.

Example:

function greet() {
    console.log("Hello!");
}
console.log(typeof greet); // Output: "function"

Best Practices for Working with Data Types

  • Use === instead of == to avoid type coercion

  • Always initialize variables to avoid undefined

  • Use const and let instead of var for block scoping

  • Be cautious with null and undefined to avoid bugs

Advanced Topics

Prototypes and Inheritance

In JavaScript, objects can inherit properties and methods from other objects through a mechanism called prototypal inheritance. Every object in JavaScript has a hidden [[Prototype]] property that links it to another object, forming a prototype chain. When you try to access a property or method on an object, JavaScript will look up the prototype chain until it finds the property or reaches the end of the chain.

Example:

const person = {
    greet: function() {
        console.log("Hello!");
    }
};

const student = Object.create(person); // student inherits from person
student.name = "John";

student.greet(); // Output: "Hello!"
console.log(student.name); // Output: "John"

In this example, student inherits the greet method from person through the prototype chain.

The prototype Property

Functions in JavaScript have a prototype property, which is used when the function is used as a constructor with the new keyword. This allows you to add methods and properties that will be shared across all instances of the object.

Example:

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name}`);
};

const john = new Person("John");
john.greet(); // Output: "Hello, my name is John"

TypeScript: Adding Static Typing to JavaScript

JavaScript is dynamically typed, which can lead to runtime errors and bugs. TypeScript is a superset of JavaScript that adds static typing, making it easier to catch errors during development. It compiles down to plain JavaScript and is widely used in large-scale application.

Example:

function add(a: number, b: number): number {
    return a + b;
}

console.log(add(2, 3)); // Output: 5
console.log(add("2", 3)); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.

TypeScript also supports features like interfaces, enums, and generics, making it a powerful tool for building robust applications.

Memory Management

Understanding how JavaScript handles memory is crucial for optimizing performance, especially in large applications. JavaScript uses automatic memory management through garbage collection. However, memory leaks can still occur if references to objects are not properly cleaned up.

Primitive vs. Non-Primitive Memory Allocation

  • Primitive Data Types: Stored in the stack, which is faster but has limited space.

  • Non-Primitive Data Types: Stored in heap, which is slower but can handle larger and more complex data structures.

Example:

let a = 10; // Stored in the stack
let b = a;  // A copy of the value is created
b = 20;
console.log(a); // Output: 10 (unchanged)

let obj1 = { name: "John" }; // Stored in the heap
let obj2 = obj1;             // A reference to the same object is created
obj2.name = "Doe";
console.log(obj1.name); // Output: "Doe" (changed)

Garbage Collection

JavaScript uses a mark-and-sweep algorithm for garbage collection. It marks all reachable objects and sweeps away the unreachable ones. However, memory leaks can occur if:

  • Unused objects are still referenced

  • Event listeners are not removed

  • Global variables are overused

Example of Memory Leak:

let button = document.getElementById("myButton");
button.addEventListener("click", function() {
    console.log("Button clicked!");
});

// Even if the button is removed from the DOM, the event listener keeps a reference to it.

To avoid memory leaks:

  • Use removeEventListener to clean up event listeners

  • Avoid creating unnecessary global variables

  • Use tools like Chrome DevTools to monitor memory usage

Conclusion

Understanding data types is fundamental to mastering JavaScript, Whether you’re working with simple primitives or complex objects, knowing how to use them effectively will make your code more robust and efficient.

JavaScript

Part 1 of 1