Data Types
JavaScript’s data types form the foundation of how values are represented and manipulated in your code. Understanding these concepts is crucial for writing efficient, predictable applications. In this section, we’ll explore the core data types in JavaScript—starting with primitives, then reference types, and finally the unique characteristic of dynamic typing.
Primitive Types
Primitive types are the simplest, most fundamental values in JavaScript. They are immutable (cannot be changed after creation) and occupy a fixed amount of memory. JavaScript has seven primitive types:
| Type | Description | Example |
|---|---|---|
number |
Numeric values (integers and floating-point numbers) | 42, 3.14, -0.001 |
string |
Text sequences (enclosed in quotes) | "Hello, world!" |
boolean |
True/false values | true, false |
null |
A placeholder for “no value” | null |
undefined |
A value that hasn’t been assigned (or the result of a non-existent property) | undefined |
symbol |
Unique, immutable values (used as object keys) | Symbol("key") |
bigint |
Integers with arbitrary precision (for very large numbers) | 123456789012345678901234567890n |
Let’s see these in action with concrete examples:
<code class="language-javascript">// Primitive type examples
<p>const num = 42; // number</p>
<p>const str = "Hello, JavaScript!"; // string</p>
<p>const bool = true; // boolean</p>
<p>const nullVal = null; // null</p>
<p>const undef = undefined; // undefined</p>
<p>const sym = Symbol("unique-key"); // symbol</p>
<p>const bigInt = 123456789012345678901234567890n; // bigint</code>
Key insight: Primitive values are copied by value when assigned. This means modifying a primitive doesn’t affect the original value:
<code class="language-javascript">let a = 10; <p>let b = a;</p> <p>b = 20;</p> <p>console.log(a); // Output: 10 (unchanged)</code>
Reference Types
Reference types represent complex, mutable objects in JavaScript. Unlike primitives, they store references (pointers) to objects in memory. These types are mutable (can be modified after creation) and include:
- Objects: Key-value pairs (e.g.,
{ name: "Alice", age: 30 }) - Arrays: Ordered collections of values (e.g.,
[1, 2, 3]) - Functions: Code blocks that can be called (e.g.,
() => console.log("Hello")) - Dates: Representations of specific points in time (e.g.,
new Date()) - Regular Expressions: Pattern-matching tools (e.g.,
/^\d+$/)
Reference types behave differently from primitives when assigned. Here’s why:
<code class="language-javascript">// Reference type example
<p>const obj = { name: "Alice" };</p>
<p>const arr = [1, 2, 3];</p>
<p>const func = () => console.log("Hello from function");</p>
<p>const date = new Date();</p>
<p>const regex = /abc/;</code>
Critical behavior: When you reassign a reference variable, you change the reference (pointer), not the original object. This means multiple variables can point to the same object:
<code class="language-javascript">// Mutating a reference type
<p>const person = { name: "Bob" };</p>
<p>const anotherPerson = person; // Both point to same object</p>
<p>anotherPerson.name = "Charlie";</p>
<p>console.log(person.name); // Output: "Charlie" (both variables reflect change)</code>
This is why reference types require careful handling—changes to an object affect all variables that reference it.
Dynamic Typing
JavaScript is a dynamically typed language. This means the type of a variable is determined at runtime, not at compile time. Unlike statically typed languages (e.g., Java, TypeScript), JavaScript doesn’t require you to declare variable types upfront.
Why dynamic typing matters:
- Flexibility: Variables can hold values of any type at any time
- Type coercion: Automatic conversion between types during operations
- Runtime checks: Type validation happens when you use values, not when you declare them
Here’s a practical demonstration:
<code class="language-javascript">// Dynamic typing in action <p>let value = 42; // Initially a number</p> <p>value = "Hello"; // Now a string (type changed at runtime)</p> <p>console.log(typeof value); // Output: "string"</p> <p>// Type coercion example</p> <p>const num1 = "5";</p> <p>const num2 = "10";</p> <p>const sum = num1 + num2; // String concatenation (not number addition)</p> <p>console.log(sum); // Output: "510" (because both are strings)</code>
Key difference from static typing: In statically typed languages, you’d get a compile-time error if you tried to assign a string to a number variable. In JavaScript, this error only appears at runtime (via typeof checks or unexpected behavior).
Summary
In this section, we’ve explored JavaScript’s foundational data types. Primitive types are immutable and represent basic values, while reference types are complex, mutable objects that store references to memory locations. JavaScript’s dynamic typing allows variables to hold values of any type at runtime, enabling flexible code but requiring careful handling of type coercion and object mutations.
✨