all topics

Data Types

Dynamically typed

Every value has a type, but a variable itself isn't locked to one. The same variable can hold a string at one moment and a number the next, no error.

js
let message = "hello";
message = 123456; // no error

That's what "dynamically typed" means: the types exist, the variables just aren't bound to any particular one.

Number

js
let n = 123;
n = 12.345;
  • One type covers both integers and floating-point numbers, no separate int vs float.
  • Comes with a few special values that still belong to this same type: Infinity, -Infinity, and NaN.
  • Infinity is bigger than any number, and shows up naturally from dividing by zero: 1 / 0Infinity.
  • NaN means "not a valid number", the result of a broken or undefined math operation, like "not a number" / 2.
  • NaN is sticky. Any further math on a NaN produces NaN again (NaN + 1, 3 * NaN, all NaN), except one oddball exception: NaN ** 0 is 1.
  • Math in JS never throws a fatal error. Divide by zero, subtract a string, whatever, worst case you get NaN back, the script keeps running.

BigInt

Regular numbers can't safely represent integers past ±(2^53 - 1) (9007199254740991), the math still runs, but precision silently breaks down past that point, 9007199254740991 + 1 and + 2 both land on the same value.

js
const bigInt = 1234567890123456789012345678901234567890n;

The trailing n is what makes a literal a BigInt, letting it represent integers of arbitrary size correctly. Rarely needed day to day, mainly cryptography and high-precision timestamps.

String

js
let str = "Hello";
let str2 = 'Single quotes are ok too';
let phrase = `can embed another ${str}`;
  • Three kinds of quotes: double, single, and backticks. Double and single are functionally identical, purely a style choice.
  • Backticks are the only ones that support embedding, ${...} runs whatever expression is inside and splices the result into the string. `Hello, ${name}!` or `the result is ${1 + 2}`, both work.
  • The same syntax inside double or single quotes does nothing, "the result is ${1 + 2}" prints literally that, ${1 + 2} included as plain text.
  • No separate "character" type, the way some languages have char. A string is a string whether it holds zero characters, one, or many.

Boolean

Two values, true and false. Used for yes/no state, and it's also what every comparison produces: 4 > 1 evaluates to true.

null vs undefined

Both stand apart, each its own type with exactly one possible value, null for null and undefined for undefined. Easy to blur together, but they mean different things:

  • null means "empty" or "unknown", something explicitly set to nothing. You write it on purpose.
  • undefined means "not assigned yet", the default a variable gets before anything's ever put into it. let age; then age is undefined automatically, nothing had to say so.
  • You can assign undefined to a variable by hand, but don't, it's meant to stay the language's own "nothing here yet" default. Use null when your own code needs to represent an empty value.

object and symbol

Everything above is "primitive", a value that's just one thing on its own. object is the odd one out, it holds collections of data and more complex structures rather than a single value. symbol exists to create guaranteed-unique identifiers. Both get their own proper treatment elsewhere, mentioned here just so the list of 8 types is complete.

The typeof operator

js
typeof undefined  // "undefined"
typeof 0           // "number"
typeof 10n         // "bigint"
typeof true        // "boolean"
typeof "foo"       // "string"
typeof Symbol("id")// "symbol"
typeof Math        // "object"
typeof null        // "object"
typeof alert       // "function"
  • typeof null returning "object" is a long-standing, officially acknowledged bug in the language, kept around only for backward compatibility. null is not an object, it's its own standalone type, typeof is just wrong here.
  • Functions aren't a separate type either, they're technically objects under the hood, but typeof reports "function" for them anyway as a practical convenience, another quirk from the language's early days.
  • typeof x and typeof(x) do the same thing. typeof is an operator, not a function, the parentheses are just ordinary grouping parens, not part of the syntax. typeof x is the far more common way to write it.

The 8 types, at a glance

Seven primitive types, number, bigint, string, boolean, null, undefined, symbol, plus one non-primitive, object. typeof tells you which one a value is, as a string, with the one caveat that null incorrectly reports as "object".