---
title: 'Primitive Types'
source: 'https://academia.sh/en/courses/javascript-fundamentals/primitive-types'
course: 'JavaScript Fundamentals'
language: en
updated: '2026-08-23T07:00:59+00:00'
license: 'CC BY-SA 4.0'
---

# Primitive Types

The seven primitive types and the distinction from objects; the single number type's floating-point representation, special number values, string, boolean, the two absence values, and symbol.

The previous topic established how names are declared and resolved. This topic takes up
the values names are bound to. The Basic Data Types lesson in the Programming Fundamentals
course defined a type as "a set of values and the operations defined on those values."
This lesson applies that definition to JavaScript's value model.

The model is small: seven primitive types and one object class. The price of that
smallness is the weight each type carries in its decisions. For example, there is a
single number type and no separate type for integers; this one decision sets the topic
for several lessons ahead.

## Seven Primitive Types and Objects

A value is either **primitive** or an **object**. Primitive values cannot have their
content changed and do not carry properties on their own. Objects are sets of properties,
and their content can be changed.

The `typeof` operator gives a value's type as text:

```js
console.log(typeof 21.5);
console.log(typeof "A1");
console.log(typeof true);
console.log(typeof undefined);
console.log(typeof null);
console.log(typeof 9007199254740993n);
console.log(typeof Symbol("measurement"));
console.log(typeof { station: "A1" });
console.log(typeof [1, 2]);
console.log(typeof function () {});
```

```
number
string
boolean
undefined
object
bigint
symbol
object
object
function
```

The output does not correspond to the type list one to one at two points. In the fifth
line, `null` is a primitive value, but the result is `object`; this is the trace of the
backward compatibility discussed in the Language Versions and Standardization lesson. In
the last line, `function` is not a separate type; functions are callable objects, and
`typeof` reports this with a distinct value.

The seven primitive types are: number, BigInt, string, boolean, `undefined`, `null`, and
symbol. This lesson's subject is six of these; BigInt is the next lesson's subject.

## Number: A Single Type

JavaScript has no separate types for integers and real numbers. The whole of the `number`
type is the IEEE 754 double-precision representation defined in the Floating-Point
Numbers lesson of the How Computers Work course: 64 bits, 1 sign bit, 11-bit biased
exponent, 52-bit stored mantissa.

This produces two direct consequences.

First, writing an integer literal does not produce a separate type:

```js
console.log(Number.isInteger(23));
console.log(23 === 23.0);
```

```
true
true
```

`23` and `23.0` are the same value; both correspond to the same bit pattern. This is why
the first lesson's `Math.max` result was written as `23` — a floating-point number whose
fractional part is zero is written without showing the fraction when converted to text.

Second, decimal values that cannot be written as a finite binary fraction are held
approximately:

```js
console.log(0.1 + 0.2);
console.log(0.1 + 0.2 === 0.3);
```

```
0.30000000000000004
false
```

This result is not a surprise, it is a direct consequence of the representation. The
model from the Floating-Point Numbers lesson applies here exactly: the values $0.1$ and
$0.2$ cannot be written as a finite binary fraction, each is rounded to the nearest
representable value, and the addition is performed on these rounded values. The result
falls not on $0.3$'s representation, but on another value closest to it.

The practical rule established in the same lesson applies here too: floating-point values
are compared not with equality but with tolerance. Quantities requiring precision, like
money, are kept as integers carrying the smallest unit.

The safe range of integers also comes from the mantissa's width. Because the mantissa
provides 53 bits of precision, integers whose absolute value exceeds $2^{53}-1$ become
indistinguishable from one another:

```js
console.log(Number.MAX_SAFE_INTEGER);
console.log(9007199254740992 === 9007199254740993);
```

```
9007199254740991
true
```

Two different integers coming out equal is because both round to the same representable
value. Cases where this boundary is crossed are the next lesson's subject.

## Special Number Values

The representation carries three special values, and all three are directly visible in
the language:

```js
console.log(1 / 0, -1 / 0, 0 / 0);
console.log(Object.is(0, -0), 1 / -0);
```

```
Infinity -Infinity NaN
false -Infinity
```

Division by zero does not throw an error; it produces an infinity value. Undefined
operations give `NaN` (not a number). `NaN` **is** a number value and its type is
`number`; its name says that what it represents is not a number.

Signed zero is also part of the representation: `0` and `-0` are different bit patterns
but are considered equal in equality comparisons. `Object.is` is the operation that sees
the distinction. The `-0` value is invisible in most computations; it only becomes
significant because it determines the sign in division by zero.

## String

The string type carries text. Strings are written with single quotes, double quotes, or
backticks; there is no behavioral difference between the first two. The backtick form has
separate capabilities and will be covered in the Strings lesson.

```js
const name = "measurement";
console.log(name.length);
console.log(name[0]);
console.log(name.toUpperCase());
console.log("A1".codePointAt(0));
```

```
11
m
MEASUREMENT
65
```

String length is not the character count, it is the count of **16-bit code units**. The
surrogate pair concept defined in the Character Encodings lesson of the How Computers
Work course becomes visible here: a code point outside the basic multilingual plane is
represented by two code units, and `length` counts it as two.

```js
console.log("😀".length);
```

```
2
```

This is the key to understanding the string type: a string is not a sequence of code
points, it is a sequence of code units. The distinction changes the result in character
counting and slicing operations.

## Boolean

The boolean type has two values: `true` and `false`. They are produced by comparisons and
are the input of conditional constructs. JavaScript also considers non-boolean values
usable in a condition; which value is considered true and which is considered false is
the subject of the Truthy and Falsy Values lesson.

## Two Absence Values

Most languages have a single absence value. JavaScript has two, and their meanings are
separate.

`undefined` is **a value never having been given at all**. A declared but unassigned
variable, a nonexistent object property, and a parameter with no corresponding argument
carry this value. The language produces it on its own.

`null` is **a deliberately placed absence**. The language does not produce it on its own;
the program's author assigns it to say "there is no value here."

```js
const record = { station: "A1", temperature: 21.5 };
console.log(record.humidity);
console.log("humidity" in record);

let nextReading;
console.log(nextReading);

const calibration = null;
console.log(calibration);
```

```
undefined
false
undefined
null
```

The distinction is directly useful in measurement data. If a record's humidity field
**does not exist at all**, reading it gives `undefined`; if the field exists but the
sensor produced no value, writing `null` preserves the information "not measured." The
two are not the same thing: the first concerns the data's shape, the second concerns the
data's content.

## Symbol

Symbol is the primitive type that produces a unique value on every call. Two symbols
produced with the same description text are not equal to each other:

```js
console.log(Symbol("source") === Symbol("source"));
```

```
false
```

Its use case is adding properties to objects with no risk of collision. Symbol-keyed
properties are invisible in ordinary key listings and in serialization:

```js
const source = Symbol("source");
const record = { station: "A1", temperature: 21.5, [source]: "local file" };
console.log(Object.keys(record));
console.log(JSON.stringify(record));
console.log(record[source]);
```

```
[ 'station', 'temperature' ]
{"station":"A1","temperature":21.5}
local file
```

The provenance information added to the measurement record was carried without polluting
the record's data content. Symbols' second role in the language — adapting objects'
specific behaviors — is the subject of the next course.

## Primitive Values Are Immutable

A primitive value's content cannot be changed. Attempting an indexed assignment on a
string throws an error in strict mode:

```js
const name = "A1";
try {
  name[0] = "B";
} catch (error) {
  console.log(error.name + ": " + error.message);
}
console.log(name);
```

```
TypeError: Cannot assign to read only property '0' of string 'A1'
A1
```

The same operation throws no error in a script not in strict mode; it is silently
ignored, and the string still does not change. This is the second example of the
strict-mode difference discussed in the Ways to Run Code lesson: the behavior is the
same, the feedback is different.

This is why string methods never modify the original value, they always produce a new
string. The immutable–mutable distinction from the Programming Fundamentals course is
strict here by type: all seven primitive types are immutable, objects are mutable.

## The Measurement Record's Types

The data that is this course's axis is a combination of these types:

```js
const record = {
  station: "A1",
  temperature: 21.5,
  humidity: null,
  verified: false,
};

for (const key of Object.keys(record)) {
  console.log(key, "->", typeof record[key]);
}
console.log("missing field:", typeof record.pressure);
```

```
station -> string
temperature -> number
humidity -> object
verified -> boolean
missing field: undefined
```

The third line is a reminder: because the `humidity` field carries `null`, the `typeof`
result comes out as `object`. Whether a field is truly empty is tested not with `typeof`
but with a direct comparison. Which rule these comparisons follow is the subject of the
Equality Comparisons lesson.

## Summary

- Values are either primitive or objects; there are seven primitive types and all of them
  are immutable.
- `typeof null` gives `object`, and functions give `function`; neither corresponds to the
  type list one to one.
- The single number type is the IEEE 754 double-precision representation: `23` and `23.0`
  are the same value, decimal fractions are approximate, and the safe integer range is
  bounded by $2^{53}-1$.
- `Infinity`, `-Infinity`, `NaN`, and `-0` are part of the representation; `NaN`'s type is
  `number`.
- String length is the code unit count, not the character count.
- `undefined` denotes a value never given, `null` a deliberately placed absence.

## Next Step

Two different integers above the safe integer range coming out equal is the one point
this lesson leaves unresolved. The next lesson takes up the cases where this boundary is
actually crossed and the language's answer to it: a separate primitive type carrying an
integer of arbitrary size, its behavior in operators, and the error that arises when it is
mixed with the number type.
