Back in JS Types you met the basic kinds of values. Now that you have used strings, numbers, arrays, objects, Maps, and more, this section goes deeper: exactly how many types there are, the one big split that divides them, and the tools for telling them apart reliably.
| Type | Example | Kind |
|---|---|---|
| string | "hello" | primitive |
| number | 42, 3.14, NaN | primitive |
| bigint | 9007199254740993n | primitive |
| boolean | true, false | primitive |
| undefined | undefined | primitive |
| null | null | primitive |
| symbol | Symbol("id") | primitive |
| object | { }, [ ], functions, dates, maps... | object |
Seven primitives, plus object. Every value in JavaScript is one of these eight. Arrays, functions, dates, Maps, Sets, and regexes are all kinds of object, not separate types.
Here is a declaration for every type, checked with typeof (every detail is in JS typeof):
const length = 16; // number
const weight = 7.5; // number (there is no separate decimal type)
const big = 1234567890123456789012345n; // bigint
const color = "Yellow"; // string
const done = false; // boolean
let nothingYet; // undefined
const empty = null; // null
const id = Symbol(); // symbol
const person = { firstName: "John", lastName: "Doe" }; // object
const cars = ["Saab", "Volvo", "BMW"]; // object (an array)
const date = new Date("2022-03-25"); // object (a Date)
console.log(typeof length, typeof big, typeof color, typeof done);
console.log(typeof nothingYet, typeof empty, typeof id, typeof person, typeof cars, typeof date);
Two surprises in the second line: typeof null says "object" (a famous bug, see JS typeof), and arrays and dates report "object" because they are objects.
BigInt(1234567890123456789012345) passes an ordinary number, which has already lost precision before BigInt sees it. The result is 1234567890123456824475648n. Use the n suffix or a string: BigInt("1234567890123456789012345").let x and let y over and over. Run as one program, the second let x is SyntaxError: Identifier 'x' has already been declared. Each pair is meant as a separate example.The single most important idea in this section. Primitives and objects behave differently when you copy, compare, and change them:
// Primitives: copied by VALUE
let a = 5;
let b = a; // b gets its own 5
b = 10;
console.log(a); // 5 (a is unaffected)
// Objects: copied by REFERENCE
const x = { n: 5 };
const y = x; // y points to the SAME object
y.n = 10;
console.log(x.n); // 10 (x sees the change)
| Primitives | Objects | |
|---|---|---|
| Assign / pass to a function | Copies the value | Shares the same object |
| Compare with === | Same value? | Same object? |
| Can be changed in place | Never | Yes |
"hi" === "hi" // true same value
[1, 2] === [1, 2] // false two different arrays
The computer has to know a value's type to know what an operator should do. What is 16 + "Volvo"? JavaScript's rule: if either side of + is a string, the other side becomes a string and the two are joined:
console.log(16 + "Volvo");
console.log("Volvo" + 16);
console.log(16 + 4 + "Volvo"); // left to right: 16 + 4 happens first
console.log("Volvo" + 16 + 4); // a string first, so everything is joined
+ works left to right. In the third line, 16 + 4 is plain math (20) before the string shows up. In the fourth, the string comes first, so 16 and then 4 are each joined as text. These automatic conversions are called type coercion, and they get their own lesson in Part 2 of this section (JS Type Coercion).
Variables do not have types; values do. The same variable can hold a string now and a number later:
let data = "42"; // string
data = Number(data); // number
data = [data]; // object (an array)
That flexibility is why the tools in this section matter: at any moment, you may need to check what kind of value you are actually holding.
typeof "hi" // "string" works well for most primitives
typeof null // "object" famous mistake: check with === null
typeof [1, 2] // "object" use Array.isArray
Array.isArray([1, 2]) // true
new Date() instanceof Date // true which constructor made it
| Primitive Data | Why primitives can never change, and how "hi".length works anyway |
| Object Types | References, shallow vs deep copies, identifying objects |
| Symbols | The least familiar primitive |
| typeof | Every result, every quirk |
| undefined | Where it comes from and how to handle it |
What does this log?
console.log(1 + 2 + "3" + 4 + 5);
3345. Left to right: 1 + 2 is 3, then 3 + "3" is the string "33", and from then on every + joins text: "334", then "3345".Which of these is not one of JavaScript's eight data types?
With let a = 5; let b = a; b = 10;, a stays 5. With const a = {n: 5}; const b = a; b.n = 10;, a.n becomes 10. Why the difference?
b gets its own 5. Objects are copied by reference, so b points to the same object as a, and a change through either name is seen by both.===, then two identical strings