JavaScript Data Types

Beginner 7 min read

JavaScript has several data types that determine what kind of values variables can hold. Understanding data types is fundamental to writing correct JavaScript code.

Data Types Overview

JavaScript has two categories of data types: primitives (immutable values) and objects (mutable references).

Note
JavaScript is dynamically typed, meaning you don't declare types when creating variables. A variable can hold any type and change types during runtime.

Primitive Types

Primitives are the most basic data types. They are immutable (cannot be changed) and compared by value.

javascript
// String - text data
const name = "Alice";
const greeting = 'Hello';
const template = `Hi, ${name}!`;

// Number - integers and decimals
const age = 25;
const price = 19.99;
const negative = -10;
const infinity = Infinity;
const notANumber = NaN;

// Boolean - true or false
const isActive = true;
const isLoggedIn = false;

// Undefined - declared but not assigned
let user;
console.log(user); // undefined

// Null - intentionally empty
const data = null;

// Symbol - unique identifier (ES6)
const id = Symbol("userId");

// BigInt - large integers (ES2020)
const huge = 9007199254740991n;

String

Strings represent text. Create them with single quotes, double quotes, or backticks (template literals).

Template Literals
Use backticks (`) for strings with variables: `Hello, ${name}!`

Number

JavaScript has a single Number type for both integers and decimals. Special values include Infinity, -Infinity, and NaN (Not a Number).

Floating Point Precision
Be careful with decimal math: 0.1 + 0.2 === 0.30000000000000004. For money calculations, use integers (cents) or a library like decimal.js.

Boolean

Booleans represent true or false. They're commonly used in conditionals and comparisons.

Null and Undefined

These represent "no value", but with different meanings:

javascript
// undefined - not assigned
let x;
console.log(x);  // undefined

function noReturn() {}
console.log(noReturn());  // undefined

const obj = {};
console.log(obj.missing);  // undefined

// null - intentionally empty
let user = null;  // "no user yet"

// Checking for both
if (value == null) {
  // true for both null and undefined
}

if (value === null) {
  // true only for null
}

if (value === undefined) {
  // true only for undefined
}

// Nullish coalescing (??)
const name = null ?? "Default";  // "Default"
const age = 0 ?? 18;            // 0 (0 is not nullish)
Note
Use null when you intentionally want "no value". Let undefined happen naturally for uninitialized variables.

Symbol (ES6)

Symbols are unique identifiers, useful for object property keys that won't collide with other properties.

BigInt (ES2020)

BigInt handles integers larger than Number.MAX_SAFE_INTEGER (9007199254740991). Create them by appending n to a number.

Object Types

Objects are collections of key-value pairs. Arrays and functions are special types of objects.

javascript
// Object - key-value pairs
const person = {
  name: "Alice",
  age: 25,
  isStudent: false
};

// Array - ordered list (special object)
const colors = ["red", "green", "blue"];
const mixed = [1, "two", true, null];

// Function - callable object
function greet(name) {
  return "Hello, " + name;
}

// Date, RegExp, Map, Set are also objects
const now = new Date();
const pattern = /hello/i;
const map = new Map();
const set = new Set([1, 2, 3]);
Tip
Unlike primitives, objects are compared by reference, not value. Two objects with the same content are not equal: {} === {} is false.

Try It Yourself

Run this example to see all data types and their typeof results:

index.js
// Primitive Types
const str = "Hello, World!";     // String
const num = 42;                   // Number
const float = 3.14;               // Number (no separate float type)
const bool = true;                // Boolean
const nothing = null;             // Null
let notDefined;                   // Undefined
const sym = Symbol("id");         // Symbol
const bigNum = 9007199254740991n; // BigInt

console.log("String:", str, "| typeof:", typeof str);
console.log("Number:", num, "| typeof:", typeof num);
console.log("Float:", float, "| typeof:", typeof float);
console.log("Boolean:", bool, "| typeof:", typeof bool);
console.log("Null:", nothing, "| typeof:", typeof nothing);
console.log("Undefined:", notDefined, "| typeof:", typeof notDefined);
console.log("Symbol:", sym.toString(), "| typeof:", typeof sym);
console.log("BigInt:", bigNum, "| typeof:", typeof bigNum);

// Reference Types
const arr = [1, 2, 3];            // Array
const obj = { name: "Alice" };    // Object
const func = function() {};       // Function

console.log("\nArray:", arr, "| typeof:", typeof arr);
console.log("Object:", obj, "| typeof:", typeof obj);
console.log("Function:", func, "| typeof:", typeof func);

Data Types Reference

TypeExampletypeof ResultPrimitive?
String"hello""string"Yes
Number42, 3.14"number"Yes
Booleantrue, false"boolean"Yes
Undefinedundefined"undefined"Yes
Nullnull"object"Yes
SymbolSymbol("id")"symbol"Yes
BigInt123n"bigint"Yes
Object{ }"object"No
Array[ ]"object"No
Functionfunction(){}"function"No

Type Checking

Use typeof to check primitive types, but be aware of its quirks:

javascript
// typeof operator
typeof "hello"     // "string"
typeof 42          // "number"
typeof true        // "boolean"
typeof undefined   // "undefined"
typeof null        // "object" (bug!)
typeof {}          // "object"
typeof []          // "object"
typeof function(){} // "function"

// Array.isArray() for arrays
Array.isArray([1, 2, 3])  // true
Array.isArray("hello")    // false

// instanceof for objects
[] instanceof Array       // true
{} instanceof Object      // true
new Date() instanceof Date // true

// Checking for null
const value = null;
value === null  // true (use strict equality)

Try the interactive type checking example:

index.js
// typeof for primitives
console.log(typeof "hello");     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof Symbol());    // "symbol"
console.log(typeof 123n);        // "bigint"

// typeof quirks
console.log("\n--- typeof quirks ---");
console.log(typeof null);        // "object" (historical bug!)
console.log(typeof [1, 2, 3]);   // "object" (arrays are objects)
console.log(typeof {});          // "object"
console.log(typeof function(){}); // "function"

// Better type checking
console.log("\n--- Better type checking ---");
console.log(Array.isArray([1, 2, 3]));  // true
console.log(Array.isArray("hello"));    // false
console.log(null === null);             // true
console.log([1,2] instanceof Array);    // true
console.log({} instanceof Object);      // true
typeof null Bug
typeof null returns "object" instead of "null". This is a historical bug that can't be fixed without breaking existing code. Always check for null with === null.

Type Coercion

JavaScript automatically converts types in certain situations. This can be helpful but also surprising:

javascript
// Implicit type coercion
console.log("5" + 3);      // "53" (number to string)
console.log("5" - 3);      // 2 (string to number)
console.log("5" * "2");    // 10 (both to numbers)
console.log(true + 1);     // 2 (true becomes 1)
console.log(false + 1);    // 1 (false becomes 0)

// Truthy and falsy values
// Falsy: false, 0, "", null, undefined, NaN
// Everything else is truthy

if ("hello") console.log("Truthy!");  // Runs
if (0) console.log("Falsy!");         // Doesn't run

// Explicit conversion
String(123)       // "123"
Number("42")      // 42
Boolean(1)        // true
parseInt("42px")  // 42
parseFloat("3.14") // 3.14
Avoid Implicit Coercion
Use explicit conversion (String(), Number()) to make your intent clear. Use === instead of == to avoid coercion in comparisons.

Best Practices

1. Use === for Comparisons
Always use strict equality (===) to avoid type coercion surprises.
2. Use Array.isArray() for Arrays
Don't rely on typeof for arrays. Use Array.isArray().
3. Initialize Variables
Avoid undefined by always initializing variables with a value.
4. Use null Intentionally
Use null to explicitly indicate "no value" rather than leaving things undefined.

Test Your Knowledge

Test Your Knowledge

5 questions
Question 1

How many primitive data types does JavaScript have?

Question 2

What does typeof null return?

Question 3

Which method correctly checks if a value is an array?

Question 4

What is the difference between null and undefined?

Question 5

What type is NaN (Not a Number)?

Practice Exercises

Challenge 1: Better Type Checking

Easy

Write a function that returns the actual type of any value, handling the quirks of typeof (null returns 'null', arrays return 'array').

Starter Code
// Challenge: Write a function that returns the actual type of any value
// It should handle the quirks of typeof

function getType(value) {
  // TODO: Return the correct type as a string
  // Examples:
  // getType(null) should return "null" (not "object")
  // getType([1,2,3]) should return "array" (not "object")
  // getType(new Date()) should return "date"
  // For primitives, return the typeof result
}

// Test cases
console.log(getType("hello"));    // should print "string"
console.log(getType(42));         // should print "number"
console.log(getType(null));       // should print "null"
console.log(getType(undefined));  // should print "undefined"
console.log(getType([1, 2, 3]));  // should print "array"
console.log(getType(new Date())); // should print "date"
console.log(getType({}));         // should print "object"

Challenge 2: Safe Property Access

Medium

Create a function that safely accesses nested object properties without throwing errors if a property doesn't exist.

Starter Code
// Challenge: Create a function that safely gets a nested property
// Return undefined if any part of the path doesn't exist

function safeGet(obj, path) {
  // path is a string like "user.address.city"
  // TODO: Return the value at that path, or undefined if it doesn't exist
}

const data = {
  user: {
    name: "Alice",
    address: {
      city: "New York",
      zip: "10001"
    }
  }
};

console.log(safeGet(data, "user.name"));         // should print "Alice"
console.log(safeGet(data, "user.address.city")); // should print "New York"
console.log(safeGet(data, "user.phone"));        // should print undefined
console.log(safeGet(data, "user.address.country")); // should print undefined

Frequently Asked Questions

Why does typeof null return "object"?

This is a bug from the first version of JavaScript that has never been fixed because it would break too much existing code. In the original implementation, values were represented with a type tag, and null had the same tag as objects.

What's the difference between == and ===?

== performs type coercion before comparing (e.g., "5" == 5 is true). === compares both value and type without coercion ("5" === 5 is false). Always prefer ===.

When should I use BigInt?

Use BigInt when working with integers larger than Number.MAX_SAFE_INTEGER (9007199254740991). Common use cases include database IDs, cryptography, and high-precision timestamps.

Are strings mutable in JavaScript?

No, strings are immutable. Methods like toUpperCase() return a new string rather than modifying the original. To "change" a string, you must reassign the variable to a new string value.

Summary

JavaScript has two categories of data types:

  • Primitives (7 types): String, Number, Boolean, Null, Undefined, Symbol, BigInt
  • Objects: Object, Array, Function, Date, RegExp, Map, Set, and more

Key takeaways:

  • Use typeof for primitives, but watch out for null and arrays
  • Use Array.isArray() to check for arrays
  • Use === for comparisons to avoid type coercion
  • Primitives are immutable and compared by value; objects are mutable and compared by reference