Programming Concepts · Chapter 1 · Foundations
Every value in JavaScript carries a type — and a dynamically typed variable can hold any of them, one after another, over its lifetime.
bookSHelf · Introduction to Programming Concepts · §1.2 · a self-paced section
Outline — by the end of this section you will be able to
typeof operator to check what type a value has Def. 1.2.8null and undefined and use each correctly Def. 1.2.5 / 1.2.6Context Pause — what “dynamically typed” means
Other languages (like Java or C++) require you to declare a variable’s type upfront and stick with it. JavaScript is more flexible — but that also means type-related bugs only show up when the code actually runs.
§1.2.1 — three values a number can be, without being a number
Definition 1.2.1 — Special Numeric Values
Besides ordinary numbers, the number type includes three special values: Infinity, -Infinity, and NaN. Infinity is larger than any number. NaN stands for “Not a Number” and represents the result of an invalid math operation.
console.log( 1 / 0 ); // Infinity console.log( "not a number" / 2 ); // NaN
Definition 1.2.1: Special numeric values — Infinity, -Infinity, and NaN.
Once NaN appears in a calculation, it spreads to the whole result. Evaluate the three checks yourself:
▶ Press Run to see the output…
Every one of them is NaN. The only exception in the whole language is NaN ** 0, which equals 1.
Insight Note — JavaScript math never crashes
Dividing by zero, multiplying a word by a number — none of it stops the program. At worst you get NaN and the code keeps running. This is different from many other languages, where such operations would halt the program with an error.
Type each line and see what JavaScript gives back:
▶ Press Run to see the output…
10 / 3 → 3.3333333333333335 100 / 0 → Infinity "hello" * 5 → NaN Infinity + 1 → Infinity
You saw 10 / 3 give 3.3333333333333335. That trailing 5 is not a display glitch. Predict both lines:
▶ Press Run to see the output…
JavaScript stores numbers in binary, and 0.1 has no exact binary form — the digits repeat forever, so the number is cut off. You already accept this in decimal: 1/3 is 0.3333... and has to stop somewhere.
Two of these four are exact and two are not. Which two — and what do they have in common?
▶ Press Run to see the output…
Exact: 0.5 + 0.25 → 0.75, 1.5 + 2.5 → 4. Not exact: both tenths cases → 0.30000000000000004.
The exact ones are halves and quarters. Binary counts in halves the way decimal counts in tenths.
§1.2.2 — when a number gets too big to trust
The number type cannot safely represent integers past 253 - 1 (9,007,199,254,740,991) — beyond that range, calculations silently lose precision.
console.log(9007199254740991 + 1); // 9007199254740992 console.log(9007199254740991 + 2); // 9007199254740992
§1.2.2 — integers with no size limit
Definition 1.2.2 — BigInt
BigInt is a data type for integers of arbitrary length. Create a BigInt by adding n to the end of an integer.
const bigInt = 1234567890123456789012345678901234567890n; console.log(bigInt);
Definition 1.2.2: BigInt is a data type for integers of arbitrary length; add n to create one.
For most everyday programming, the regular number range is plenty. But BigInt is essential for cryptography, precise timestamps, and any situation where very large integers must be exact.
In the console, try:
▶ Press Run to see the output…
Once numbers get past 253 - 1, regular number math becomes unreliable. The n suffix means BigInt handles 9007199254740994n exactly.
§1.2.3 — three quote marks, two behaviors
Definition 1.2.3 — Three Types of Quotes
Double quotes "Hello" and single quotes 'Hello' are “simple” quotes — they work the same way. Backticks `Hello` let us embed variables and expressions directly using ${...}.
let name = "John";
console.log( `Hello, ${name}!` ); // Hello, John!
Definition 1.2.3: backticks evaluate ${...} to embed variables and expressions.
Context Pause — only backticks evaluate ${...}
Only backticks support ${...} embedding. Double and single quotes treat ${...} as literal text — they never evaluate it.
console.log( "the result is ${1 + 2}" ); // the result is ${1 + 2}
Create a variable with your name and use backticks to print a greeting, then try the same thing with single quotes instead:
▶ Press Run to see the output…
Backticks: Hello, Alex! Today is 2025. Single quotes: Hello, ${myName}! Today is ${2024 + 1}. — the ${...} prints as literal text.
Two questions come up about a string constantly: how long is it, and what sits at a particular spot. JavaScript answers both with no method call — but positions start at 0, not 1. Predict every line:
▶ Press Run to see the output…
The space in "a b" counts — a character is a character, including the ones you cannot see. And the last line is the one to remember: word[6] is not an error. There is no sixth position in a six-character string, so JavaScript answers undefined rather than complaining.
§1.2.3 — the first thing a string can do
Example 1.2.4 — String Methods
A method is an action attached to a value, written with a dot after it: value.actionName(). Strings come with methods built in. The parentheses are what run the action.
let city = "portland"; console.log( city.toUpperCase() ); // PORTLAND console.log( city.toLowerCase() ); // portland
What happens to city itself is the subject of the next slide.
Predict what this prints:
▶ Press Run to see the output…
It prints ada — not ADA, and not an error. The method ran, produced "ADA", and threw it away.
Strings are immutable. toUpperCase() cannot alter name, so it returns a new string. To keep it, catch it:
Three of these lines leave word unchanged. Which single line changes it?
▶ Press Run to see the output…
Only word = word.toLowerCase(); changes it — the block prints stressed. The first three discard their result.
Assignment is what changes a variable. A method call on its own never does.
§1.2.4 — a yes/no value
Definition 1.2.4 — Boolean
The boolean type has exactly two values: true and false. Booleans are used to store yes/no answers, and often come from comparisons.
let isGreater = 4 > 1; console.log( isGreater ); // true
Definition 1.2.4: exactly two values, true and false, often produced by a comparison.
Try these comparisons and see what boolean value each one produces:
▶ Press Run to see the output…
Every comparison produces a boolean — true or false, never anything else. === compares value and type, which is why "apple" === "orange" is a comparison and not an error.
§1.2.5 — a value that means “nothing,” on purpose
Definition 1.2.5 — null
null is a special value that belongs to its own type. It represents “nothing,” “empty,” or “value unknown.” It simply means “this variable intentionally has no value right now.”
let age = null; console.log(age);
Definition 1.2.5: null represents “nothing,” “empty,” or “value unknown.”
Declare a variable set to null and check what typeof gives you:
▶ Press Run to see the output…
console.log(empty) prints null. console.log(typeof empty) prints "object" — a known bug. null is not an object; it is its own type.
§1.2.6 — the value JavaScript gives you by default
Definition 1.2.6 — undefined
undefined is a special value that means “value is not assigned.” When you declare a variable but do not give it a value, JavaScript automatically sets it to undefined.
let age; console.log(age); // "undefined"
Definition 1.2.6: a declared-but-unassigned variable is automatically set to undefined.
Insight Note — undefined vs. null
Use null when you want to say “this variable is intentionally empty.” Think of undefined as JavaScript’s way of saying “you forgot to give this a value,” and null as your way of saying “I am deliberately setting this to nothing.”
Declare a variable without assigning it, then check its value and type:
▶ Press Run to see the output…
console.log(futureValue) prints undefined. console.log(typeof futureValue) prints "undefined". The variable exists, but has no value yet.
§1.2.7 — one value vs. a collection of them
Definition 1.2.7 — Primitive vs. Object Types
number, string, boolean, null, undefined, and bigint are called primitive types — each can hold only one thing. The object type is different: it stores collections of data and more complex entities.
A seventh primitive, symbol, creates unique identifiers, mostly for advanced object work.
Definition 1.2.7: primitives hold a single value; object stores collections of data.
Create a simple object and check its type:
▶ Press Run to see the output…
console.log(typeof book) prints "object". The curly braces { } create an object that holds multiple pieces of data.
§1.2.8 — asking a value what it is
Definition 1.2.8 — typeof
The typeof operator returns a string telling us the type of a value. It is useful when we need to check what kind of data we are working with.
console.log(typeof 0); // "number" console.log(typeof null); // "object" (bug)
Definition 1.2.8: typeof returns a string telling us the type of a value.
Three results need extra explanation: typeof Math is "object" (correct — Math is a built-in object); typeof null is "object" (a famous early bug); typeof alert is "function" (functions are a kind of object, but typeof reports them separately).
Use typeof to check the type of several different values:
▶ Press Run to see the output…
Five values, five honest answers — and one that lies. typeof null reports "object", a bug from JavaScript’s first week that is now too widely relied on to fix. null is its own type.
§1.2.9 — the word every example has started with
Every code block so far has begun a line with let. This section is what that word has been doing.
let score; // declared, empty -- holds undefined score = 10; // assigned let player = "Ada"; // declared and assigned in one line
§1.2.9 — three words for making a variable
Definition 1.2.9 — let, const, and var
let makes a variable you can reassign. const makes one you cannot — use it whenever the value should not change, which is most of the time. var is the original keyword from 1995; it still works and you will meet it in older code, but it behaves differently in a way that caused years of bugs. Do not write new code with it.
const pi = 3.14159; let radius = 2; radius = 5; // let allows this pi = 3; // TypeError
Definition 1.2.9: let and const stop at the closing brace; var does not.
A pair of braces { } marks off a block. Blocks are what if statements and loops are built from in Chapter 2. Predict both lines:
▶ Press Run to see the output…
undefined, then string — inner is gone outside its block; outer escaped.
let is block-scoped; var is function-scoped and ignores braces. That difference is why let was added in 2015.
This needs no var — only a forgotten let. Predict the output:
▶ Press Run to see the output…
It prints 100. Assigning to an undeclared name does not fail — JavaScript creates it at the outermost level, where any other code can overwrite it.
§1.2.9 — the one-line fix
Example 1.2.6 — continued
A variable meant to stay in one small piece of code is now visible to the whole program, and nothing warned you. One line at the top of the file changes that:
▶ Press Run to see the output…
"use strict" turns the silent accident into an error that names the line.
Insight Note — the dangerous bug is the one that works
A program that crashes tells you where to look. A program that runs and produces a wrong answer gives you nothing to search for. "use strict" is the first of several tools in this course whose whole job is to convert the second kind into the first.
Predict each block. One of the three stops with an error.
▶ Press Run to see the output…
1 → 1 (inner x is a separate variable) 2 → 2 (var ignores the braces) 3 → TypeError
Blocks 1 and 2 differ by one word and give different answers. That is the reason to write let.
Glossary — terms introduced in this section
data type
A classification that tells the language what kind of value a variable holds.
dynamically typed
Variables are not bound to a single type; the type can change at runtime.
number / NaN / BigInt
Ordinary and floating-point numbers, including Infinity/NaN; BigInt handles integers beyond the safe range.
string
Text, enclosed in quotes or backticks.
boolean
A data type with only two values: true and false.
null / undefined
null is a deliberate “empty on purpose”; undefined is JavaScript’s automatic “no value yet.”
primitive type / object
A primitive holds a single value; an object stores a collection of data.
typeof
An operator that returns a string naming the type of a value.
The headline result of §1.2
JavaScript has 8 data types
Seven primitives that each hold a single value — number, bigint, string, boolean, null, undefined, symbol — plus one non-primitive: object, which holds collections of data.
Dynamically typed: a variable is whatever value it currently holds.
† typeof null returns "object" — a famous bug from JavaScript’s earliest days, kept for compatibility. null is not an object; it is its own type.
§1.2 — Conclusions
Every value has a type, and JavaScript decides that type from what a variable currently holds, not from a declaration up front. Use typeof x to check what you have.
null and undefined look similar but mean different things — undefined is JavaScript’s own “no value yet,” null is a deliberate “empty on purpose.” And watch for typeof null — it wrongly reports "object".
Next: §1.3 Documentation and Coding Conventions. Back to start.