-
-
Notifications
You must be signed in to change notification settings - Fork 2
JavaScript Beginner Part2
In this part, we'll learn how to make decisions in your code (control flow), repeat actions (loops), and organize code into reusable blocks (functions). These are fundamental concepts that every programmer needs to master.
Control flow determines the order in which your code executes. Think of it like a road map - depending on conditions, you take different paths.
The if statement is the most basic way to make decisions in JavaScript.
let temperature = 25;
if (temperature > 30) {
console.log("It's hot outside!");
}let age = 18;
if (age >= 18) {
console.log("You can vote!");
} else {
console.log("You are too young to vote.");
}let score = 85;
if (score >= 90) {
console.log("Grade: A");
} else if (score >= 80) {
console.log("Grade: B");
} else if (score >= 70) {
console.log("Grade: C");
} else if (score >= 60) {
console.log("Grade: D");
} else {
console.log("Grade: F");
}let age = 25;
let hasLicense = true;
if (age >= 18) {
if (hasLicense) {
console.log("You can drive!");
} else {
console.log("You need to get a license first.");
}
} else {
console.log("You are too young to drive.");
}// Good: Use curly braces even for single statements
if (isLoggedIn) {
showDashboard();
}
// Good: Put the positive case first
if (isValid) {
processData();
} else {
showError();
}
// Good: Extract complex conditions into variables
let canAccess = isLoggedIn && hasPermission && !isSuspended;
if (canAccess) {
showContent();
}The switch statement is useful when you have many conditions to check against a single value.
let day = 3;
let dayName;
switch (day) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
case 4:
dayName = "Thursday";
break;
case 5:
dayName = "Friday";
break;
case 6:
dayName = "Saturday";
break;
case 7:
dayName = "Sunday";
break;
default:
dayName = "Invalid day";
}
console.log(dayName); // "Wednesday"let grade = "A";
switch (grade) {
case "A":
case "B":
case "C":
console.log("You passed!");
break;
case "D":
case "F":
console.log("You failed.");
break;
default:
console.log("Invalid grade");
}function getDayType(day) {
switch (day) {
case "Saturday":
case "Sunday":
return "Weekend";
case "Monday":
case "Tuesday":
case "Wednesday":
case "Thursday":
case "Friday":
return "Weekday";
default:
return "Invalid";
}
}
console.log(getDayType("Monday")); // "Weekday"
console.log(getDayType("Saturday")); // "Weekend"The ternary operator is a shorthand for simple if...else statements.
// condition ? valueIfTrue : valueIfFalse
let age = 20;
let status = age >= 18 ? "adult" : "minor";
console.log(status); // "adult"let score = 85;
let grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" :
score >= 60 ? "D" : "F";
console.log(grade); // "B"// Setting default value
let userName = "";
let displayName = userName ? userName : "Guest";
console.log(displayName); // "Guest"
// Conditional rendering (React-like)
let isOnline = true;
let statusColor = isOnline ? "green" : "red";
// Conditional class
let isActive = true;
let buttonClass = isActive ? "btn btn-primary" : "btn btn-secondary";Loops allow you to repeat code multiple times. This is incredibly useful for processing lists of items, performing calculations, and automating repetitive tasks.
The for loop is the most commonly used loop in JavaScript.
// for (initialization; condition; increment) { code }
for (let i = 1; i <= 5; i++) {
console.log("Iteration " + i);
}
// Output:
// Iteration 1
// Iteration 2
// Iteration 3
// Iteration 4
// Iteration 5// The for loop has 3 parts separated by semicolons:
for (
let i = 0; // 1. Initialization: runs once at the start
i < 5; // 2. Condition: checked before each iteration
i++ // 3. Increment: runs after each iteration
) {
console.log(i);
}
// Execution order:
// 1. i = 0, check 0 < 5 (true), print 0, increment to 1
// 2. i = 1, check 1 < 5 (true), print 1, increment to 2
// 3. i = 2, check 2 < 5 (true), print 2, increment to 3
// 4. i = 3, check 3 < 5 (true), print 3, increment to 4
// 5. i = 4, check 4 < 5 (true), print 4, increment to 5
// 6. i = 5, check 5 < 5 (false), stopfor (let i = 5; i > 0; i--) {
console.log(i);
}
console.log("Blast off!");
// Output:
// 5
// 4
// 3
// 2
// 1
// Blast off!// Even numbers (0, 2, 4, 6, 8)
for (let i = 0; i < 10; i += 2) {
console.log(i);
}
// Counting by 3s (0, 3, 6, 9)
for (let i = 0; i <= 12; i += 3) {
console.log(i);
}for (let i = 0, j = 10; i < 5; i++, j--) {
console.log("i:", i, "j:", j);
}
// Output:
// i: 0 j: 10
// i: 1 j: 9
// i: 2 j: 8
// i: 3 j: 7
// i: 4 j: 6The while loop repeats as long as a condition is true.
let count = 0;
while (count < 5) {
console.log("Count is: " + count);
count++;
}
console.log("Done!");// Simulating a game where player has 3 lives
let lives = 3;
while (lives > 0) {
console.log("You have " + lives + " lives left");
// Imagine player loses a life here
lives--;
}
console.log("Game Over!");// NEVER do this - it will crash your browser/node
// while (true) {
// console.log("This will run forever!");
// }
// Always have a way to exit
let input = "yes";
while (input !== "quit") {
console.log("Processing...");
// In real code, input would come from user
input = "quit"; // This exits the loop
}The do...while loop always runs at least once, then checks the condition.
let count = 0;
do {
console.log("Count: " + count);
count++;
} while (count < 5);
// Output:
// Count: 0
// Count: 1
// Count: 2
// Count: 3
// Count: 4// while - might not run at all
let whileCount = 10;
while (whileCount < 5) {
console.log("while: " + whileCount);
}
// Nothing prints - condition false from start
// do...while - runs at least once
let doCount = 10;
do {
console.log("do...while: " + doCount);
} while (doCount < 5);
// Prints "do...while: 10" - runs once before checkingThe for...of loop is perfect for iterating over arrays and other iterable objects.
let fruits = ["apple", "banana", "cherry"];
for (let fruit of fruits) {
console.log(fruit);
}
// Output:
// apple
// bananalet message = "Hello";
for (let char of message) {
console.log(char);
}
// Output:
// H
// e
// l
// l
// olet colors = new Set(["red", "green", "blue"]);
for (let color of colors) {
console.log(color);
}The for...in loop iterates over the enumerable properties of an object.
let person = {
name: "Alice",
age: 25,
city: "New York"
};
for (let key in person) {
console.log(key + ": " + person[key]);
}
// Output:
// name: Alice
// age: 25
// city: New Yorklet scores = [95, 87, 92, 88];
// This works but gives you INDEXES, not values
for (let index in scores) {
console.log(index + ": " + scores[index]);
}
// Use for...of instead for arrays:
for (let score of scores) {
console.log(score);
}// Find the first number divisible by 7
for (let i = 1; i <= 100; i++) {
if (i % 7 === 0) {
console.log("Found it: " + i);
break; // Exit the loop
}
}
// Output: Found it: 7// Print only odd numbers
for (let i = 1; i <= 10; i++) {
if (i % 2 === 0) {
continue; // Skip even numbers
}
console.log(i);
}
// Output: 1, 3, 5, 7, 9// Skip invalid data
let data = [1, 2, "invalid", 4, 5, "bad", 7];
for (let item of data) {
if (typeof item !== "number") {
continue; // Skip non-numbers
}
console.log("Valid number:", item);
}
// Find first match
let users = [
{ name: "Alice", active: false },
{ name: "Bob", active: true },
{ name: "Charlie", active: false }
];
let firstActiveUser;
for (let user of users) {
if (user.active) {
firstActiveUser = user.name;
break; // Found what we need, stop searching
}
}
console.log("First active user:", firstActiveUser); // "Bob"Functions are reusable blocks of code. They help you organize code, avoid repetition, and make your programs easier to understand.
A function declaration defines a named function.
// Function declaration
function greet(name) {
return "Hello, " + name + "!";
}
// Calling the function
let message = greet("Alice");
console.log(message); // "Hello, Alice!"
// You can call the function before it's declared (hoisting)
console.log(add(2, 3)); // 5
function add(a, b) {
return a + b;
}function fullName(firstName, lastName) {
return firstName + " " + lastName;
}
console.log(fullName("John", "Doe")); // "John Doe"
console.log(fullName("Jane")); // "Jane undefined"function greet(name = "Guest") {
return "Hello, " + name + "!";
}
console.log(greet("Alice")); // "Hello, Alice!"
console.log(greet()); // "Hello, Guest!"A function expression assigns a function to a variable.
// Function expression
let greet = function(name) {
return "Hello, " + name + "!";
};
console.log(greet("Bob")); // "Hello, Bob!"// Function declaration - can be called before definition
sayHello("Alice"); // Works!
function sayHello(name) {
console.log("Hello, " + name);
}
// Function expression - CANNOT be called before definition
// sayGoodbye("Bob"); // Error!
let sayGoodbye = function(name) {
console.log("Goodbye, " + name);
};
sayGoodbye("Bob"); // Works!Arrow functions are a shorter syntax introduced in ES6.
// Traditional function
function add(a, b) {
return a + b;
}
// Arrow function
let add = (a, b) => {
return a + b;
};
// Short form (implicit return)
let add = (a, b) => a + b;
console.log(add(2, 3)); // 5// Single parameter - no parentheses needed
let square = x => x * x;
console.log(square(5)); // 25
// No parameters
let getRandom = () => Math.random();
console.log(getRandom());
// Multiple statements need curly braces and return
let calculate = (a, b) => {
let sum = a + b;
let product = a * b;
return { sum, product };
};
console.log(calculate(3, 4)); // { sum: 7, product: 12 }Arrow functions don't have their own this binding - they inherit from the parent scope.
// Traditional function - 'this' changes
let person1 = {
name: "Alice",
greet: function() {
console.log("Hello, " + this.name);
}
};
// Arrow function - 'this' is lexical (inherited)
let person2 = {
name: "Bob",
greet: () => {
console.log("Hello, " + this.name); // 'this' is NOT person2
}
};
person1.greet(); // "Hello, Alice"
person2.greet(); // "Hello, undefined" (or error in strict mode)// Collect multiple arguments into an array
function sum(...numbers) {
let total = 0;
for (let num of numbers) {
total += num;
}
return total;
}
console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3, 4, 5)); // 15function oldSum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(oldSum(1, 2, 3, 4)); // 10let numbers = [1, 2, 3, 4, 5];
// Spread operator expands array into individual arguments
console.log(Math.max(...numbers)); // 5
console.log(Math.min(...numbers)); // 1
function greet(greeting, ...names) {
for (let name of names) {
console.log(greeting + ", " + name + "!");
}
}
greet("Hello", "Alice", "Bob", "Charlie");
// Hello, Alice!
// Hello, Bob!
// Hello, Charlie!// Return a single value
function add(a, b) {
return a + b;
}
// Return multiple values using objects
function calculate(a, b) {
return {
sum: a + b,
difference: a - b,
product: a * b,
quotient: a / b
};
}
let result = calculate(10, 5);
console.log(result.sum); // 15
console.log(result.product); // 50
// Return a function (closure)
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
let double = multiplier(2);
let triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15Scope determines where variables are accessible in your code.
// Variables declared outside functions are global
let globalVar = "I'm global";
function accessGlobal() {
console.log(globalVar); // Can access global variables
}
accessGlobal(); // "I'm global"
console.log(globalVar); // "I'm global"function myFunction() {
let functionVar = "I'm inside function";
console.log(functionVar); // Works here
}
// console.log(functionVar); // Error! Not accessible outside
function testScope() {
let x = 1;
function inner() {
let y = 2;
console.log(x); // Can access x
console.log(y); // Can access y
}
inner();
// console.log(y); // Error! y is not accessible here
}if (true) {
let blockVar = "I'm in a block";
const blockConst = "Also in block";
console.log(blockVar); // Works
}
// console.log(blockVar); // Error! Block scoped
for (let i = 0; i < 3; i++) {
console.log(i); // Works
}
// console.log(i); // Error!let outer = "outer";
function outerFunction() {
let inner = "inner";
function innerFunction() {
console.log(outer); // Can access outer
console.log(inner); // Can access inner
}
innerFunction();
}
outerFunction();Hoisting is JavaScript's behavior of moving declarations to the top of their scope.
// console.log(myVar); // undefined (not an error)
var myVar = 5;
// JavaScript interprets this as:
// var myVar; // Declaration hoisted to top
// console.log(myVar); // undefined
// myVar = 5; // Assignment stays in place
// let and const are hoisted but not initialized (Temporal Dead Zone)
console.log(myLet); // ReferenceError
let myLet = 10;// Function declarations are fully hoisted
console.log(add(2, 3)); // 5
function add(a, b) {
return a + b;
}
// Function expressions are partially hoisted
// console.log(multiply(2, 3)); // TypeError!
var multiply = function(a, b) {
return a * b;
};// Good: Declare variables at the top of their scope
function goodPractice() {
let result;
let data;
// Use variables later
result = processData(data);
function processData(d) {
return d * 2;
}
return result;
}
// Good: Declare functions before using them (or use function expressions)
let calculate = function(a, b) {
return a + b;
};