Essential Foundations for Modern Web Development (AI-Assisted Learning)
2025-10-12
Our Goal: Get You Ready for React
Not: Make you JavaScript experts
But: Give you just enough to start building with AI assistance
Philosophy: Learn what you need NOW. Deep dives come later when you’re actually using them.
Translation: We’re teaching you to drive, not to build a car! 🚗
Part 1: JavaScript Essentials
Part 2: Async Basics
Part 3: React Motivation
Optional Reading:
Remember from Session 1: The AI-First Approach
You are the senior developer 🎯
AI is your junior assistant 🤖
Today: Every code example generated with AI. You’ll learn to verify, not memorize!
If You Know PHP, You’re Ahead!
Concept | PHP | JavaScript |
---|---|---|
Variables | $name = "Alice"; |
const name = "Alice"; |
Arrays | [1, 2, 3] |
[1, 2, 3] (same!) |
Functions | function greet($n) {...} |
function greet(n) {...} |
Control | if , for , while |
Same syntax! |
Key differences to watch:
$
prefix->
operator (use .
)Good news: 70% of your backend knowledge transfers! Focus on the 30% that’s different.
Learning Objectives (Part 1)
By the end of this section, you’ll be able to:
const
and let
correctly (never var
)Remember: You don’t need to memorize syntax. You need to recognize correct patterns!
Let’s Generate Some Code!
Prompt to AI:
Create a JavaScript object representing a product with
name, price, and inStock properties. Use const.
Expected AI Output:
Your Verification:
const
? (Good!)Everyone try this now in your console! (F12 → Console)
Traditional Function
When to use which? Arrow functions for short operations, traditional for complex logic.
// Object: Key-value pairs (like PHP associative arrays)
const user = {
name: "Alice",
age: 25,
email: "alice@example.com"
};
// Access with dot notation
console.log(user.name); // "Alice"
console.log(user.age); // 25
// Arrays: Ordered lists
const products = [
{name: "Laptop", price: 999},
{name: "Mouse", price: 25},
{name: "Keyboard", price: 75}
];
// Access by index
console.log(products[0].name); // "Laptop"
console.log(products.length); // 3
For PHP developers: Objects = associative arrays, but use .
not [
]
map: Transform Each Item
const prices = [10, 20, 30];
// Add tax to each price
const withTax = prices.map(price =>
price * 1.2
);
console.log(withTax);
// [12, 24, 36]
Use when: You need to transform every item
filter: Select Items
const products = [
{name: "Laptop", price: 999},
{name: "Mouse", price: 25},
{name: "Keyboard", price: 75}
];
// Only expensive items
const expensive = products.filter(
p => p.price > 50
);
console.log(expensive);
// [{name: "Laptop", ...},
// {name: "Keyboard", ...}]
Use when: You need to select some items
React uses these CONSTANTLY! Get comfortable with the pattern.
Challenge: Generate & Verify
Use AI to create:
Your CRISP Prompt:
Create a JavaScript array of 3 products with name, price,
and category. Then create two functions:
1. filterByPrice(products, minPrice) - returns products >= minPrice
2. addTax(products, taxRate) - returns products with tax added to price
Use modern JavaScript (const, arrow functions, map/filter).
Verify:
.
not ->
Are you ready for async? Let’s learn to fetch data! 🚀
❌ Synchronous (PHP-style)
1. Take order from table 1
→ WAIT for kitchen →
2. Deliver food to table 1
→ WAIT for them to finish →
3. Take order from table 2
→ WAIT for kitchen →
4. Deliver food to table 2
Problem: One customer at a time!
Restaurant: Empty while waiting
Code: Frozen UI while fetching data
✅ Asynchronous (JavaScript)
1. Take order table 1 → kitchen
2. Take order table 2 → kitchen
3. Take order table 3 → kitchen
(while kitchen cooks)
4. Deliver food as ready
5. Keep taking new orders
Benefit: Serve many customers!
Restaurant: Always busy
Code: Responsive UI while loading
The Pattern You’ll Use Everywhere
async function fetchData() {
try {
// 1. Mark function as async
// 2. Use await to pause until promise resolves
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
return data;
} catch (error) {
// 3. Handle errors
console.error('Something went wrong:', error);
}
}
Three parts:
async
keyword on functionawait
keyword before promisestry/catch
for errorsThis is ALL you need to know about async for now!
The Pattern
Common Mistakes
// ❌ Forgot async
function getUsers() {
await fetch(url); // ERROR!
}
// ❌ Forgot await
async function getUsers() {
const response = fetch(url);
// response is Promise, not data!
}
// ❌ Forgot .json()
async function getUsers() {
const response = await fetch(url);
console.log(response);
// Just response object, not data!
}
Let’s Fetch Real Data!
Prompt to AI:
Create an async function that fetches users from
https://jsonplaceholder.typicode.com/users
and returns only their names as an array.
Use async/await and proper error handling.
Expected Pattern:
async function getUserNames() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
const names = users.map(user => user.name);
return names;
} catch (error) {
console.error('Error fetching users:', error);
return [];
}
}
Everyone test this in your console now!
async function fetchProducts() {
try {
const response = await fetch('https://api.example.com/products');
// Check if request was successful
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const products = await response.json();
return products;
} catch (error) {
console.error('Failed to fetch products:', error);
// Return empty array or default value
return [];
}
}
Pro tip: Always check response.ok
before parsing JSON!
Challenge: Fetch Real Data
Use AI to create a function that:
https://jsonplaceholder.typicode.com/posts
Your CRISP Prompt:
Create an async function fetchUserPosts(userId) that:
- Fetches posts from https://jsonplaceholder.typicode.com/posts
- Filters for posts matching the userId parameter
- Returns an array of just the post titles
- Includes try/catch error handling
- Checks response.ok before parsing JSON
Test it: fetchUserPosts(1)
should return array of titles
.then()
syntax (confusing)Promise.all()
, Promise.race()
You don’t need them yet!
Philosophy: Just-in-time learning
Next session (Express): We’ll cover POST, headers, authentication, parallel requests, etc.
Ready for React motivation? Let’s see why we need it! 🎨
15 Minutes: From Vanilla JS Pain to React Joy
Session 2 Summary: You now know enough JavaScript to:
But: Building complex UIs with vanilla JavaScript becomes painful…
Optional Content - Read Later
The following content contains valuable DOM manipulation concepts, but they’re optional for this session due to time constraints.
When to read: After Session 3 (React), when you want to understand what React does behind the scenes.
File reference: See webdev_02_L_02C_JavaScriptAdvanced.qmd
for more advanced patterns.
Original 30-Minute Content (Now Optional)
HTML (What You Write)
DOM (Browser’s View)
// Browser creates JavaScript objects
document = {
head: { /* ... */ },
body: {
children: [
{type: "h1", id: "title", ...},
{type: "button", id: "btn", ...}
]
}
}
// You can manipulate these objects!
DOM = JavaScript’s way to access and modify HTML
Modern Element Selection
// Select by ID
const title = document.querySelector('#title');
// Select by class
const button = document.querySelector('.btn-primary');
// Select by tag
const firstDiv = document.querySelector('div');
// Complex selectors (like CSS!)
const item = document.querySelector('ul > li:first-child');
const button = document.querySelector('button.active[data-id="5"]');
Why just querySelector? - Works for everything (ID, class, tag, complex) - Same syntax as CSS selectors - Modern and flexible
Old methods (getElementById, getElementsByClassName) - forget them!
✅ Safe Way: textContent
const title = document
.querySelector('#title');
// Read content
console.log(title.textContent);
// "Hello"
// Update content (safe!)
title.textContent = "New Title";
// Even with user input (safe!)
const userInput = "<script>alert('hack')</script>";
title.textContent = userInput;
// Shows literal text, not code
⚠️ Dangerous: innerHTML
const container = document
.querySelector('#container');
// Read HTML
console.log(container.innerHTML);
// "<p>Hello</p>"
// Update HTML (dangerous!)
container.innerHTML = "<p>New</p>";
// User input (DANGEROUS!)
const userInput = "<script>alert('hack')</script>";
container.innerHTML = userInput;
// Executes the script! ⚠️
Only use innerHTML with trusted content!
// 1. Select the element
const button = document.querySelector('#loadButton');
// 2. Add event listener
button.addEventListener('click', () => {
console.log('Button clicked!');
});
// With async function
button.addEventListener('click', async () => {
const data = await fetch('https://api.example.com/data');
const json = await data.json();
console.log(json);
});
// Form submit
const form = document.querySelector('#myForm');
form.addEventListener('submit', (event) => {
event.preventDefault(); // Stop form from reloading page!
console.log('Form submitted');
});
Pattern: querySelector
+ addEventListener
= Interactive page
Let’s Make a Button Work!
Prompt to AI:
Create JavaScript code that:
1. Selects a button with id "loadBtn"
2. Adds a click event listener
3. When clicked, fetches a random user from
https://jsonplaceholder.typicode.com/users/1
4. Displays the user's name in an element with id "output"
5. Uses async/await and textContent
HTML Setup (try in CodePen):
Everyone try this - see vanilla JS in action!
// This is what you'll do in vanilla JavaScript:
// 1. Select elements
const button = document.querySelector('#loadBtn');
const output = document.querySelector('#output');
// 2. Add event listener
button.addEventListener('click', async () => {
// 3. Fetch data
const response = await fetch('https://api.example.com/products');
const products = await response.json();
// 4. Update DOM manually (tedious!)
output.textContent = ''; // Clear first
products.forEach(product => {
const div = document.createElement('div');
div.textContent = `${product.name} - $${product.price}`;
output.appendChild(div);
});
});
Notice: Manual DOM manipulation is tedious! Imagine 100 products, multiple updates…
getElementById
, getElementsByClassName
createElement
, appendChild
patternsinnerHTML
(dangerous anyway)React replaces ALL of this!
// Vanilla JS: 20 lines
const div = document.createElement('div');
div.textContent = product.name;
div.addEventListener('click', handler);
document.body.appendChild(div);
// React: 1 line
<div onClick={handler}>{product.name}</div>
You’ll learn the React way next week
// Manual DOM updates
productsDiv.innerHTML = '';
products.forEach(product => {
const div = document
.createElement('div');
div.textContent = product.name;
productsDiv.appendChild(div);
});
// Managing state manually
let isLoading = false;
let products = [];
let error = null;
// No automatic re-rendering
// You update DOM yourself!
// Declarative rendering
return products.map(product => (
<div>{product.name}</div>
));
// State management built-in
const [products, setProducts]
= useState([]);
// Automatic re-rendering
setProducts(newProducts);
// React updates DOM automatically!
// Component reusability
<ProductCard product={p} onAddToCart={handleAdd} />
Vanilla JS gets exponentially harder: - ❌ Add filter by price? Manual DOM rebuild - ❌ Add sorting? More DOM manipulation - ❌ Add shopping cart? Track state everywhere - ❌ Add product details? More event listeners - ❌ Update individual items? Find element, update manually - ❌ Add animations? Complex DOM manipulation
React stays manageable: - ✅ Filter: products.filter(...)
in render - ✅ Sort: products.sort(...)
in render - ✅ Cart: const [cart, setCart] = useState([])
- ✅ Details: <ProductDetails product={selected} />
- ✅ Update: setProducts(...)
- React handles DOM! - ✅ Animations: Built-in transition tools
React’s Superpowers 🦸♀️
Components - Reusable UI pieces
State Management - Automatic UI updates
Declarative - Describe what you want, not how
Virtual DOM - React optimizes updates for you
Ecosystem - React Router, Redux, thousands of libraries
Self-Check ✅
Can you:
If you checked 6+ boxes: You’re ready! 🚀
If you checked fewer: Review the reference docs, practice more
FAQ
Q: “Do I need to memorize all this JavaScript?”
A: No! Use AI to generate, you verify. Focus on patterns.
Q: “Why not teach promises and callbacks?”
A: async/await is simpler and modern. Learn others when needed.
Q: “Why so little DOM?”
A: React replaces it all! Just need to understand what React automates.
Q: “What if I want to deep dive?”
A: Read the reference docs! Everything’s there for curious students.
Q: “Is vanilla JS ever useful?”
A: Yes! Small scripts, browser extensions, understanding React better.
Q: What about TypeScript?
A: TypeScript is great! But adds complexity. Learn JavaScript first.
E. Bruno - JavaScript for React