Data Types & typeof in JavaScript
JavaScript is a dynamically typed language, meaning that variables are not directly associated with any particular value type, and any variable can be assigned (and re-assigned) values of all types.
The Two Main Categories
JavaScript data types can be broadly divided into two categories:
- Primitives (Value Types): Immutable data types that hold a single value.
- Objects (Reference Types): Collections of properties and methods.
1. Primitive Data Types
As of modern JavaScript (ES6+), there are 7 primitive data types:
String
Represents a sequence of characters used to represent text.
const name = "Alice";
const greeting = `Hello, ${name}!`; // Template literal
Number
Represents both integer and floating-point numbers. Unlike some other languages, JavaScript does not have separate types for integers and floats (except for BigInt).
const age = 30;
const pi = 3.14159;
Special numeric values: NaN (Not-a-Number), Infinity, and -Infinity are also of type Number.
BigInt
Introduced to represent whole numbers larger than Number.MAX_SAFE_INTEGER (). Created by appending n to the end of an integer.
const largeNumber = 9007199254740991n;
Boolean
Represents a logical entity and can have two values: true and false.
const isOnline = true;
Undefined
A variable that has not been assigned a value is of type undefined.
let user;
console.log(user); // undefined
Null
Represents the intentional absence of any object value. It is one of JavaScript's primitive values and is treated as falsy for boolean operations.
const emptyValue = null;
Symbol
Introduced in ES6, a Symbol is a unique and immutable primitive value, often used as an identifier for object properties.
const id = Symbol('id');
2. Object (Reference Type)
Objects are complex data structures that can contain combinations of primitive and reference types. Everything that is not a primitive is technically an Object under the hood.
This includes:
- Plain Objects:
{ key: "value" } - Arrays:
[1, 2, 3] - Functions:
function() {} - Dates, Maps, Sets, RegExp, etc.
const user = {
name: "Alice",
age: 25,
hobbies: ["reading", "coding"]
};
3. The typeof Operator
The typeof operator returns a string indicating the type of the unevaluated operand.
Common Uses:
typeof "John" // "string"
typeof 3.14 // "number"
typeof NaN // "number"
typeof true // "boolean"
typeof undefined // "undefined"
typeof Symbol() // "symbol"
typeof 1234n // "bigint"
typeof function(){} // "function" (a special callable object)
The typeof null Quirk (The "Billion Dollar Mistake")
One of the most famous quirks in JavaScript is how typeof null behaves.
typeof null; // "object"
Why? In the first implementation of JavaScript, values were represented as a type tag and a value. The type tag for objects was 0. null was represented as the NULL pointer (which is 0x00 in most platforms). Consequently, null had 0 as a type tag, causing the typeof operator to return "object". A proposal to fix this was rejected because it would break existing legacy code.
To properly check for null, use strict equality:
if (value === null) { /* ... */ }
4. Dynamic Typing
Because JavaScript is dynamically typed, variables are not bound to a specific data type. You can reassign a variable to a value of a completely different type without errors.
let dynamicVar = "Hello World"; // Currently a String
dynamicVar = 42; // Now a Number
dynamicVar = true; // Now a Boolean
While this provides flexibility, it can also lead to bugs where unexpected data types are passed into functions. This is why tools like TypeScript have become extremely popular in modern web development to enforce static typing.
Conclusion
Understanding JavaScript's data types and the nuances of the typeof operator is essential for debugging and writing predictable code. Be mindful of primitives vs. references, and always watch out for the null quirk!