4.2: Variables, Data Types & Operators
Master JavaScript operators and control flow structures including conditionals and loops. Learn how to make decisions in code and execute repetitive tasks efficiently using if statements, switch cases, and various loop types.
1. Variables Deep Dive
Variable Scope
Block Scope (let and const):
{
let x = 10;
const y = 20;
console.log(x, y); // 10, 20
}
// console.log(x); // Error: x is not defined
Function Scope (var):
function test() {
var x = 10;
if (true) {
var y = 20; // Same scope as x!
}
console.log(x, y); // 10, 20 (y is accessible)
}
// console.log(x); // Error: x is not defined
Python comparison:
def test():
x = 10
if True:
y = 20
print(x, y) # Works - Python has function scope for variables
# print(x) # Error: x not defined outside function
Hoisting
JavaScript "hoists" variable declarations to the top:
console.log(x); // undefined (not error!)
var x = 5;
// What JavaScript actually does:
var x;
console.log(x); // undefined
x = 5;
let and const are NOT hoisted:
// console.log(y); // Error: Cannot access before initialization
let y = 5;
Best practice: Always declare variables at the top of their scope.
Temporal Dead Zone
{
// TDZ for x starts here
console.log(x); // Error: Cannot access 'x' before initialization
let x = 10; // TDZ ends here
}
const with Objects
const prevents reassignment, but NOT mutation:
const user = { name: "Alice", age: 30 };
// user = {}; // Error: Cannot reassign
user.age = 31; // OK: Mutating object
user.city = "NYC"; // OK: Adding property
console.log(user); // { name: "Alice", age: 31, city: "NYC" }
Python comparison:
# Python has no true const, but convention uses UPPERCASE
USER = {"name": "Alice", "age": 30}
USER["age"] = 31 # Allowed - Python has no immutable dict by default
2. Number Type
Number Basics
JavaScript has one number type for integers and floats:
let integer = 42;
let float = 3.14;
let negative = -10;
let scientific = 2.5e6; // 2,500,000
console.log(typeof integer); // "number"
console.log(typeof float); // "number"
Python comparison:
integer = 42 # int
float_num = 3.14 # float
# Different types!
Special Numeric Values
let infinity = Infinity;
let negInfinity = -Infinity;
let notNumber = NaN; // Not a Number
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log("hello" * 2); // NaN
// Check for special values
console.log(isFinite(100)); // true
console.log(isFinite(Infinity)); // false
console.log(isNaN(NaN)); // true
console.log(isNaN("hello")); // true
Number Precision
JavaScript uses 64-bit floating point (IEEE 754):
console.log(0.1 + 0.2); // 0.30000000000004
console.log(0.1 + 0.2 === 0.3); // false!
// Solution: Round or compare with epsilon
console.log((0.1 + 0.2).toFixed(1)); // "0.3"
Python has same issue:
0.1 + 0.2 # 0.30000000000000004
Number Methods
let num = 123.456;
num.toFixed(2); // "123.46" (string!)
num.toPrecision(4); // "123.5" (string!)
num.toString(); // "123.456" (string)
Number(num.toFixed(2)); // 123.46 (back to number)
Math Object
Math.PI; // 3.141592653589793
Math.E; // 2.718281828459045
Math.round(4.7); // 5
Math.ceil(4.1); // 5
Math.floor(4.9); // 4
Math.trunc(4.9); // 4 (removes decimal)
Math.abs(-5); // 5
Math.pow(2, 3); // 8
Math.sqrt(16); // 4
Math.cbrt(27); // 3 (cube root)
Math.max(1, 5, 3); // 5
Math.min(1, 5, 3); // 1
Math.random(); // Random between 0 and 1
Math.floor(Math.random() * 10); // Random 0-9
Python comparison:
import math
math.pi # 3.141592653589793
round(4.7) # 5
math.ceil(4.1) # 5
math.floor(4.9) # 4
abs(-5) # 5
pow(2, 3) # 8 or 2**3
math.sqrt(16) # 4.0
max(1, 5, 3) # 5
min(1, 5, 3) # 1
import random
random.random() # Random 0-1
3. String Type
String Creation
let single = 'Single quotes';
let double = "Double quotes";
let backtick = `Template literal`;
// All create the same type
console.log(typeof single); // "string"
String Concatenation
let first = "Hello";
let last = "World";
// Old way: concatenation
let greeting = first + " " + last; // "Hello World"
// Modern way: template literals
let greeting2 = `${first} ${last}`; // "Hello World"
Python comparison:
first = "Hello"
last = "World"
greeting = first + " " + last # "Hello World"
greeting = f"{first} {last}" # f-string (like template literals)
Template Literals
let name = "Alice";
let age = 30;
// Multi-line strings
let message = `
Hello ${name}!
You are ${age} years old.
Next year you'll be ${age + 1}.
`;
// Expressions in template literals
let price = 19.99;
let tax = 0.08;
console.log(`Total: $${(price * (1 + tax)).toFixed(2)}`); // Total: $21.59
Python comparison:
name = "Alice"
age = 30
# Multi-line f-string
message = f"""
Hello {name}!
You are {age} years old.
Next year you'll be {age + 1}.
"""
String Properties and Methods
let text = "JavaScript";
// Property
text.length; // 10
// Methods (immutable - return new string)
text.toUpperCase(); // "JAVASCRIPT"
text.toLowerCase(); // "javascript"
text.charAt(0); // "J"
text[0]; // "J" (array-like access)
text.indexOf("Script"); // 4
text.lastIndexOf("a"); // 3
text.includes("Script"); // true
text.startsWith("Java"); // true
text.endsWith("Script"); // true
text.slice(0, 4); // "Java"
text.slice(-6); // "Script"
text.substring(4, 10); // "Script"
text.replace("Java", "Type"); // "TypeScript"
text.replaceAll("a", "A"); // "JAvAScript"
text.trim(); // Remove whitespace
text.split(""); // ["J", "a", "v", "a", ...]
text.repeat(2); // "JavaScriptJavaScript"
Python comparison:
text = "JavaScript"
len(text) # 10
text.upper() # "JAVASCRIPT"
text.lower() # "javascript"
text[0] # "J"
text.index("Script") # 4
"Script" in text # True
text.startswith("Java") # True
text.endswith("Script") # True
text[0:4] # "Java"
text[-6:] # "Script"
text.replace("Java", "Type") # "TypeScript"
text.strip() # Remove whitespace
text.split("") # Error: empty separator
list(text) # ["J", "a", "v", "a", ...]
String Immutability
let str = "Hello";
str[0] = "h"; // No effect - strings are immutable
console.log(str); // "Hello"
// Must create new string
str = "h" + str.slice(1); // "hello"
Same in Python:
str = "Hello"
# str[0] = "h" # Error: strings are immutable
str = "h" + str[1:] # "hello"
4. Boolean Type
Boolean Values
let isTrue = true;
let isFalse = false;
console.log(typeof isTrue); // "boolean"
Python:
is_true = True # Capitalized
is_false = False
Truthy and Falsy
Falsy values (evaluate to false):
Boolean(false); // false
Boolean(0); // false
Boolean(-0); // false
Boolean(0n); // false (BigInt zero)
Boolean(""); // false (empty string)
Boolean(null); // false
Boolean(undefined); // false
Boolean(NaN); // false
Everything else is truthy:
Boolean(true); // true
Boolean(1); // true
Boolean(-1); // true
Boolean("0"); // true (string "0", not number 0)
Boolean("false"); // true (any non-empty string)
Boolean([]); // true (empty array)
Boolean({}); // true (empty object)
Boolean(function(){}); // true
Python comparison:
# Falsy: False, 0, 0.0, "", [], {}, None
bool([]) # False (different from JavaScript!)
bool({}) # False
Boolean Conversion
// Explicit conversion
Boolean(1); // true
Boolean(0); // false
// Implicit conversion (in conditionals)
if (1) {
console.log("Truthy!"); // Runs
}
if ("") {
console.log("Won't run");
}
// Double negation (common trick)
let hasValue = !!"hello"; // true
let isEmpty = !!""; // false
5. Null and Undefined
Undefined
Undefined means "no value assigned":
let x;
console.log(x); // undefined
function test() {}
console.log(test()); // undefined (no return)
let obj = {};
console.log(obj.nonExistent); // undefined
Null
Null means "intentionally empty":
let empty = null; // Explicitly set to nothing
let user = null; // User not logged in
if (user === null) {
console.log("Please log in");
}
Null vs Undefined
typeof undefined; // "undefined"
typeof null; // "object" (JavaScript bug!)
null === undefined; // false
null == undefined; // true (loose equality)
// Best practice: use null for intentional absence
let user = null; // Not logged in (intentional)
let result; // undefined (uninitialized)
Python comparison:
# Python only has None (similar to null)
user = None
if user is None:
print("Not logged in")
6. Type Conversion
Explicit Conversion
To String:
String(123); // "123"
String(true); // "true"
String(null); // "null"
String(undefined); // "undefined"
(123).toString(); // "123"
true.toString(); // "true"
To Number:
Number("123"); // 123
Number("12.5"); // 12.5
Number("hello"); // NaN
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
Number(""); // 0 (empty string!)
parseInt("123"); // 123
parseInt("123.45"); // 123 (truncates)
parseFloat("123.45"); // 123.45
parseInt("123px"); // 123 (stops at non-digit)
To Boolean:
Boolean(1); // true
Boolean(0); // false
Boolean("hello"); // true
Boolean(""); // false
// Double negation trick
!!"hello"; // true
!!0; // false
Python comparison:
str(123) # "123"
int("123") # 123
float("123.45") # 123.45
bool(1) # True
bool(0) # False
# int("123px") # Error (Python is stricter)
Implicit Conversion (Coercion)
String coercion:
"3" + 2; // "32" (number → string)
"3" + 2 + 1; // "321"
2 + 1 + "3"; // "33"
Number coercion:
"3" - 2; // 1 (string → number)
"3" * "2"; // 6
"6" / "2"; // 3
"5" - true; // 4 (true → 1)
Boolean coercion:
if ("hello") { // "hello" → true
console.log("Truthy");
}
let x = 5 || 10; // 5 (first truthy value)
let y = 0 || 10; // 10
let z = null ?? 10; // 10 (nullish coalescing)
7. Operators
Arithmetic Operators
10 + 5; // 15 (addition)
10 - 5; // 5 (subtraction)
10 * 5; // 50 (multiplication)
10 / 5; // 2 (division)
10 % 3; // 1 (remainder/modulo)
10 ** 2; // 100 (exponentiation)
// Increment/Decrement
let x = 5;
x++; // 6 (post-increment)
++x; // 7 (pre-increment)
x--; // 6 (post-decrement)
--x; // 5 (pre-decrement)
Assignment Operators
let x = 10;
x += 5; // x = x + 5 → 15
x -= 3; // x = x - 3 → 12
x *= 2; // x = x * 2 → 24
x /= 4; // x = x / 4 → 6
x %= 4; // x = x % 4 → 2
x **= 3; // x = x ** 3 → 8
Python has same:
x = 10
x += 5 # 15
x -= 3 # 12
# etc.
Comparison Operators
// Strict equality (use these!)
5 === 5; // true
5 === "5"; // false
5 !== "5"; // true
// Loose equality (avoid!)
5 == "5"; // true (type coercion)
0 == false; // true
"" == false; // true
null == undefined; // true
// Relational
5 > 3; // true
5 < 3; // false
5 >= 5; // true
5 <= 4; // false
Logical Operators
// AND (&&)
true && true; // true
true && false; // false
// OR (||)
true || false; // true
false || false; // false
// NOT (!)
!true; // false
!false; // true
// Short-circuit evaluation
let x = 0 || 10; // 10 (0 is falsy)
let y = 5 || 10; // 5 (first truthy)
let z = 5 && 10; // 10 (last truthy)
let a = 0 && 10; // 0 (first falsy)
Python:
# and, or, not (keywords)
True and True # True
True or False # True
not True # False
Nullish Coalescing (??)
// Returns right side if left is null/undefined
let x = null ?? 10; // 10
let y = undefined ?? 10; // 10
let z = 0 ?? 10; // 0 (0 is not null/undefined)
let a = "" ?? "default"; // "" (empty string is not null/undefined)
// Compare to ||
let b = 0 || 10; // 10 (0 is falsy)
let c = 0 ?? 10; // 0 (0 is not null/undefined)
Ternary Operator
// condition ? valueIfTrue : valueIfFalse
let age = 18;
let status = age >= 18 ? "Adult" : "Minor"; // "Adult"
// Nested ternary (use sparingly)
let grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "F";
Python:
age = 18
status = "Adult" if age >= 18 else "Minor"
Operator Precedence
From highest to lowest:
// 1. Grouping ()
(2 + 3) * 4; // 20
// 2. Member access, function call
obj.prop
func()
// 3. Exponentiation **
2 ** 3; // 8
// 4. Unary + - ! typeof
!true
// 5. Multiplication * / %
2 * 3 + 4; // 10
// 6. Addition + -
2 + 3 * 4; // 14
// 7. Comparison < <= > >=
5 > 3 && 2 < 4; // true
// 8. Equality == === != !==
5 === 5 && 3 === 3; // true
// 9. Logical AND &&
true && false || true; // true
// 10. Logical OR ||
false || false && true; // false
// 11. Assignment = += -= etc
let x = 5 + 3; // Assignment last
Use parentheses for clarity:
// Unclear
let result = 2 + 3 * 4 ** 2; // ?
// Clear
let result = 2 + (3 * (4 ** 2)); // 50
8. Practical Examples
Example 1: Temperature Converter
function celsiusToFahrenheit(celsius) {
return (celsius * 9/5) + 32;
}
function fahrenheitToCelsius(fahrenheit) {
return (fahrenheit - 32) * 5/9;
}
console.log(celsiusToFahrenheit(0)); // 32
console.log(celsiusToFahrenheit(100)); // 212
console.log(fahrenheitToCelsius(32)); // 0
Example 2: String Formatter
function formatName(firstName, lastName) {
const full = `${firstName} ${lastName}`;
return {
full: full,
uppercase: full.toUpperCase(),
lowercase: full.toLowerCase(),
initials: `${firstName[0]}${lastName[0]}`.toUpperCase()
};
}
console.log(formatName("john", "doe"));
// {
// full: "john doe",
// uppercase: "JOHN DOE",
// lowercase: "john doe",
// initials: "JD"
// }
Example 3: Safe Division
function safeDivide(a, b) {
if (b === 0) {
return "Cannot divide by zero";
}
return a / b;
}
console.log(safeDivide(10, 2)); // 5
console.log(safeDivide(10, 0)); // "Cannot divide by zero"
Example 4: Type Checker
function getType(value) {
if (value === null) return "null";
if (Array.isArray(value)) return "array";
return typeof value;
}
console.log(getType(42)); // "number"
console.log(getType("hello")); // "string"
console.log(getType(null)); // "null"
console.log(getType([1, 2, 3])); // "array"
9. Practical Exercises
Exercise 4.2.1: Variable Scope
Create examples demonstrating:
- Block scope with
letandconst - Function scope with
var - Why
constcan't prevent object mutation
Exercise 4.2.2: Type Conversion Challenge
Write functions to:
- Safely convert string to number (return NaN if invalid)
- Convert any value to boolean
- Format numbers to 2 decimal places
Exercise 4.2.3: String Manipulation
Create a function that:
- Takes a full name (e.g., "john doe")
- Returns title case (e.g., "John Doe")
- Handles multiple spaces
- Works with hyphenated names (e.g., "jean-paul sartre")
Exercise 4.2.4: Calculator
Build a calculator function that:
- Takes operator (+, -, *, /, **, %)
- Takes two numbers
- Returns result or error message
- Handles division by zero
10. Knowledge Check
Question 1: What's the difference between null and undefined?
Show answer
`undefined` means a variable has been declared but not assigned. `null` is an intentional absence of value. Use `null` to explicitly indicate "no value".Question 2: Why does typeof null return "object"?
Show answer
This is a JavaScript bug from the original implementation that can't be fixed for backward compatibility reasons.Question 3: What's the difference between == and ===?
Show answer
`==` performs type coercion (5 == "5" is true). `===` checks type AND value (5 === "5" is false). Always use `===`.Question 4: What are falsy values in JavaScript?
Show answer
false, 0, -0, 0n, "" (empty string), null, undefined, NaN. Everything else is truthy, including "0", "false", [], {}.Question 5: What does 0.1 + 0.2 === 0.3 return and why?
Show answer
Returns `false`. JavaScript uses IEEE 754 floating point, which has precision issues: 0.1 + 0.2 = 0.30000000000004.Question 6: What's the difference between || and ???
Show answer
`||` returns first truthy value. `??` (nullish coalescing) only checks for null/undefined. `0 || 10` returns 10, but `0 ?? 10` returns 0.11. Key Takeaways
- Use
constby default,letfor reassignment, nevervar letandconstare block-scoped,varis function-scoped- JavaScript has one
numbertype for integers and floats - Strings are immutable and have many useful methods
- Template literals
`${expr}`are like Python f-strings - Falsy values: false, 0, "", null, undefined, NaN (everything else is truthy)
nullis intentional absence,undefinedis unassigned- Always use
===(strict equality), not== - Type coercion happens automatically (especially with
+) ??(nullish coalescing) is safer than||for default values- Use
typeoffor type checking (but it returns "object" for null and arrays)
12. Further Resources
Documentation:
Tools:
Next Steps
Great work! You now understand JavaScript's type system and operators in depth.
In Lesson 4.3: Functions & Scope, you'll learn how to write functions in JavaScript, understand scope and closures, and explore arrow functions and higher-order functions.
Next: Lesson 4.3 - Functions & Scope →