JavaScript Data Types

JavaScript values have a type that determines what you can do with them. There are two categories: primitives and objects.

Primitives are simple, immutable values. Objects are collections of data that can hold multiple values.

Primitive types

JavaScript has seven primitive types.

Number

Numbers cover integers, decimals, and special numeric values.

const age = 28;
const price = 9.99;
const temperature = -5;

Two special number values are worth knowing:

  • NaN (Not a Number): the result of an invalid maths operation.
  • Infinity: produced by dividing a number by zero.
console.log(10 / 'hello'); // NaN
console.log(1 / 0);        // Infinity

String

Strings are text, wrapped in single quotes, double quotes, or backticks (template literals).

const name = 'Anna';
const city = "Copenhagen";
const greeting = `Hello, ${name}!`; // template literal

Boolean

Booleans have two values: true or false. They are used for conditions and flags.

const isLoggedIn = true;
const hasPermission = false;

The following values are considered falsy in JavaScript (they behave like false in a condition): false, 0, '', null, undefined, and NaN. Everything else is truthy.

Undefined

undefined means a variable has been declared but not yet assigned a value.

let score;
console.log(score); // undefined

Null

null represents the intentional absence of a value. You set something to null on purpose to signal it has no value.

const selectedUser = null; // no user selected yet

The difference from undefined: undefined means “not yet assigned”, null means “deliberately empty”.

Symbol (ES2015)

Symbols are unique, immutable identifiers. They are mainly used to create private-ish object property keys that will not clash with other keys.

const id = Symbol('id');
const anotherId = Symbol('id');

console.log(id === anotherId); // false (every Symbol is unique)

Symbols come up in library code and advanced patterns. You will not need them often when starting out.

BigInt (ES2020)

Regular JavaScript numbers have a maximum safe integer value of 2^53 - 1. BigInt lets you work with integers larger than that.

const bigNumber = 9007199254740991n; // note the 'n' suffix
const result = bigNumber + 1n;
console.log(result); // 9007199254740992n

Use BigInt when working with very large numbers, such as database IDs that exceed the safe integer limit.

Objects

Everything that is not a primitive is an object. Objects store collections of key-value pairs.

const user = {
  name: 'Anna',
  age: 28,
  isAdmin: false,
};

Arrays and functions are also objects under the hood, even though they look different.

const colours = ['red', 'green', 'blue']; // array (a type of object)

function greet(name) {                     // function (also an object)
  return `Hello, ${name}`;
}

See the Objects section for a full guide.

The typeof operator

typeof tells you the type of a value. It returns a string.

console.log(typeof 42);          // 'number'
console.log(typeof 'hello');     // 'string'
console.log(typeof true);        // 'boolean'
console.log(typeof undefined);   // 'undefined'
console.log(typeof Symbol());    // 'symbol'
console.log(typeof 1n);          // 'bigint'
console.log(typeof {});          // 'object'
console.log(typeof []);          // 'object'
console.log(typeof function(){}); // 'function'

One well-known quirk: typeof null returns 'object', even though null is a primitive. This is a long-standing bug in JavaScript that has never been fixed because fixing it would break too much existing code.

console.log(typeof null); // 'object' (this is misleading, but it is how it works)

Type coercion

JavaScript automatically converts types in certain situations. This is called type coercion, and it can catch you off guard.

The + operator with a string triggers string concatenation:

console.log('5' + 3);  // '53' (number 3 is converted to string '3')
console.log('5' + '3'); // '53'

Other arithmetic operators force numeric conversion:

console.log('5' - 3);  // 2  (string '5' is converted to number 5)
console.log('5' * 2);  // 10
console.log('10' / 2); // 5

Always use === for comparisons

The loose equality operator == does type coercion before comparing, which produces results that are hard to predict.

console.log(0 == false);   // true  (type coercion)
console.log('' == false);  // true  (type coercion)
console.log(null == undefined); // true (they are treated as equal by ==)

The strict equality operator === compares both value and type, without any coercion.

console.log(0 === false);   // false
console.log('' === false);  // false
console.log(null === undefined); // false

Use === and !== in your code. The loose versions (== and !=) are rarely what you want.

Common mistakes

Comparing with == instead of ===: The results of == comparisons can be hard to predict. Get into the habit of always using ===.

Assuming null and undefined are the same: They both represent the absence of a value, but they are not identical. null === undefined is false. They are only loosely equal with ==.

console.log(null === undefined); // false
console.log(null == undefined);  // true (loose equality only)

See the Variables page for how types interact with const and let, and the Objects section for working with object types.