JavaScript has seven primitive types (number, bigint, string, boolean, undefined, null and symbol) and one object type, which covers plain objects, arrays, functions, dates and every other structure. Primitives are immutable: string methods return new strings. The language is dynamically typed, so a variable can hold a number now and a string later. typeof reports a value's type; Object.prototype.toString reads the finer built-in tag.
const samples = { "42": 42, "42n": 42n, '"hi"': "hi", "undefined": undefined, "null": null,
"Symbol()": Symbol(), "[]": [], "class {}": class {} };
for (const [src, v] of Object.entries(samples)) {
console.log(src.padEnd(10), (typeof v).padEnd(10), Object.prototype.toString.call(v));
}
let x = 5;
x = "five"; // dynamic typing: only the value has a type
console.log(typeof x, Array.isArray([]), 5 + "5", "5" * 2);42 number [object Number]
42n bigint [object BigInt]
"hi" string [object String]
undefined undefined [object Undefined]
null object [object Null]
Symbol() symbol [object Symbol]
[] object [object Array]
class {} function [object Function]
string true 55 10typeof null is "object" because the first implementation tagged objects with 0 and represented null as the null pointer, also 0; a proposal to fix it was rejected. Arrays also report "object", so test them with Array.isArray(). The last line shows implicit conversion: + with a string concatenates, * converts to numbers.