02. Variables and Types
`const` cannot be reassigned, `let` can, and `var` has function-scope and hoisting issues that make it unsuitable for modern code. Default to `const`, switch to `let` only when the value must change.
What you'll learn
- 1Explain the difference between `let`, `const`, and `var` and choose the right one.
- 2Distinguish the 7 primitive types in JavaScript.
- 3Predict the result of explicit and implicit type conversions.
- 4Identify truthy / falsy values and use them in conditions.
- 5Use the `typeof` operator to inspect a value's type.
Overview
`const` cannot be reassigned, `let` can, and `var` has function-scope and hoisting issues that make it unsuitable for modern code. Default to `const`, switch to `let` only when the value must change.
Core Concepts
1. Declarations: const, let, var
`const` cannot be reassigned, `let` can, and `var` has function-scope and hoisting issues that make it unsuitable for modern code. Default to `const`, switch to `let` only when the value must change.
const PI = 3.14;
let count = 0;
count += 1;2. Primitive types
JavaScript has 7 primitive types: `string`, `number`, `boolean`, `null`, `undefined`, `symbol`, `bigint`. Unlike objects, primitives are compared and copied by value.
typeof "hi"; // "string"
typeof 42; // "number"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" β historical bug3. Type coercion
Explicit conversions use `Number()`, `String()`, `Boolean()`. Implicit ones happen automatically with operators like `+` and `==`. Unintended coercion is a common source of bugs, so prefer explicit conversion.
Number("42"); // 42
String(42); // "42"
"5" + 1; // "51" (string concatenation)
"5" - 1; // 4 (numeric conversion)4. truthy / falsy
Only 7 values are falsy in a condition: `false`, `0`, `-0`, `0n`, `""`, `null`, `undefined`, `NaN`. Everything else is truthy.
if ("") console.log("does not run");
if ("0") console.log("runs - non-empty string");Examples
| File | What it covers |
|---|---|
| `01_let_const.js` | const vs let β reassignment and scope |
| `02_primitives.js` | The 7 primitive types and `typeof` |
| `03_conversion.js` | Explicit vs implicit conversions |
| `04_truthy_falsy.js` | How truthy/falsy works in conditions |
src/01_let_const.js
/** Compare the behavior of const and let. */
const name = "Ada";
let age = 30;
age += 1;
console.log(`${name}, ${age}`);
// You can still mutate the contents of a const object
const user = { name: "Linus" };
user.name = "Grace";
console.log("user:", user);
try {
// user = {}; // reassignment fails β TypeError
} catch (e) {
console.error(e.message);
}
src/02_primitives.js
/** Inspect the 7 primitive types with typeof. */
const samples = [
"hello",
42,
true,
undefined,
null,
Symbol("id"),
10n,
];
for (const v of samples) {
console.log(String(v).padEnd(15), "β", typeof v);
}
src/03_conversion.js
/** Compare explicit and implicit type conversion. */
console.log(Number("42")); // 42
console.log(Number("42px")); // NaN
console.log(parseInt("42px")); // 42
console.log(String(123)); // "123"
console.log(Boolean(0)); // false
// Implicit conversion
console.log("5" + 1); // "51"
console.log("5" - 1); // 4
console.log("5" * "2"); // 10
console.log(+"3.14"); // 3.14
src/04_truthy_falsy.js
/** Verify the 7 falsy values. */
const falsyValues = [false, 0, -0, 0n, "", null, undefined, NaN];
for (const v of falsyValues) {
console.log(`${String(v).padEnd(10)} β ${Boolean(v)}`);
}
// Common gotchas
console.log("'0' β", Boolean("0")); // true (non-empty string)
console.log("[] β", Boolean([])); // true (an object)
console.log("{} β", Boolean({})); // true
Common Mistakes
- Thinking you can't mutate the properties of a `const` object (only reassignment is blocked β mutation is fine).
- Forgetting that `typeof null === "object"` and writing the null check incorrectly.
- Knowing that `parseInt("10px")` is `10` but being surprised that `Number("10px")` is `NaN`.
- Falling into `==` traps like `"" == false` or `0 == false`. Prefer `===`.
- Using `var` when `let` is enough, then hitting hoisting bugs.
FAQ
Q1. Should I always reach for const first?
Yes. Switch to let only when reassignment is required β it makes intent clear.
Q2. What's the difference between `null` and `undefined`?
`undefined` means "no value was ever assigned", while `null` means "intentionally empty".
Q3. When do I use BigInt?
When you need integers larger than `Number.MAX_SAFE_INTEGER (2^53 - 1)`. Day-to-day arithmetic doesn't need it.
Practice
- `homework_01.js` β Print the `typeof` of several different values.
- `homework_02.js` β Take a string input (as a constant), convert it to a number, and decide whether it's even or odd.
homework/README.md
## homework_01.js
- Put at least 6 values of different types into an array and print each value alongside its `typeof`.
- Include `null` β and add a comment noting what `typeof null` returns.
## homework_02.js
- Convert a constant string input to a number.
- If conversion fails, print "Not a number".
- If it succeeds, print whether it's even or odd.
homework/answer/homework_01.js
/** Print typeof for a variety of values. */
const values = ["text", 3.14, true, undefined, null, Symbol("k"), 99n, { a: 1 }];
for (const v of values) {
// Note: typeof null === "object" is a leftover bug from the early days.
console.log(`${String(v).padEnd(12)} β ${typeof v}`);
}
homework/answer/homework_02.js
/** Convert a string to a number and check even/odd. */
const input = "42";
const n = Number(input);
if (Number.isNaN(n)) {
console.log("Not a number");
} else if (n % 2 === 0) {
console.log(`${n} is even`);
} else {
console.log(`${n} is odd`);
}
Next Lecture
[03_Operators_and_Expressions](../03_μ°μ°μμ_ννμ/) β Tools for computing and comparing values.
All lecture materials and example code are openly available on GitHub.
View on GitHub β