| Tag | Purpose |
|---|---|
<header> |
Introductory content, site branding, navigation |
<nav> |
Major navigation links |
<main> |
Main unique content (one per page) |
<article> |
Self-contained content (blog post, comment) |
<section> |
Thematic grouping of related content |
<aside> |
Sidebar, related links, supplementary info |
<footer> |
Page footer, copyright, related links |
<figure> |
Self-contained illustration, diagram, photo |
<figcaption> |
Caption for <figure> |
alt text on all images<label> tagsaria-label for icon buttonsrole attributes for custom components| Input Type | Description |
|---|---|
text |
Single-line text input |
password |
Password input (masked) |
email |
Email address input with validation |
number |
Numeric input with optional min/max |
checkbox |
Multiple selection options |
radio |
Single selection from a group |
submit |
Submit the form data |
Remember to use the correct form attributes like:
<section> instead of <div>?<div> is a generic container with no semantic meaning, while <section> groups related content that usually has a heading and gives structure to the page.<article> and <section>?<article> is a self-contained piece of content that should still make sense on its own, while a <section> groups related content under a common theme.<span> used for?<span> is an inline element mainly used to style or target part of a sentence or word without breaking the flow of text.| Promises | Async/Await |
|---|---|
| Chainable with .then/.catch | Syntactic sugar over Promises, reads like sync code |
| Good for parallel flows (Promise.all) | Good for sequential flows and readability |
| Must handle rejections with .catch | Use try/catch for errors |
| Works in older environments with polyfills | Requires async-capable runtime or transpile |
// create 23 promises and await them
const tasks = Array.from({length:23}, (_,i) =>
new Promise((res) => setTimeout(() => res(i+1), 10 + (i%5)*10))
);
// parallel with Promise.all
Promise.all(tasks).then(results => console.log('parallel results', results));
// sequential with async/await
async function runSequential(){
const out = [];
for(const t of tasks){
out.push(await t);
}
console.log('sequential results', out);
}
runSequential();
Shorter syntax; lexical `this` binding.
const nums = [1,2,3];
const squares = nums.map(n => n*n);
const obj = {
val: 10,
getVal: () => this.val // `this` is lexical, not the object
};
`let` and `const` are block-scoped; `const` is immutable binding.
for(let i=0;i<3;i++){
setTimeout(()=>console.log(i), 10); // prints 0,1,2
}
const a = {x:1};
a.x = 2; // allowed; binding immutable, properties mutable
const [a,b=2] = [1];
const {name='anon'} = {};
function f({x=0,y=0} = {}){ return x+y }
const a = [1,2];
const b = [...a,3];
function sum(...nums){ return nums.reduce((s,n)=>s+n,0) }
// module.js
export function add(a,b){ return a+b }
// main.js
import { add } from './module.js';
console.log(add(1,2));
Use localStorage for data that should persist across browser sessions, and sessionStorage for temporary data that should disappear when the tab closes.
localStorage.setItem('theme', 'dark');
const theme = localStorage.getItem('theme');
sessionStorage.setItem('step', '2');
class Animal{ constructor(name){ this.name = name } speak(){ return this.name } }
class Dog extends Animal{ bark(){ return 'woof' }}
const d = new Dog('Fido');
const s = new Set([1,2,2]);
const m = new Map([['k', 'v']]);
console.log(s.has(1), m.get('k'));
function* gen(){ yield 1; yield 2 }
const it = gen();
console.log(it.next().value);
The CSS box model describes the rectangular boxes generated for elements in the document tree and consists of:
<div class="box-container">
<div class="box">1</div>
<div class="box">2</div>
<!-- repeat for 23 boxes -->
</div>
.box-container { padding: 12px; border: 2px solid #1976d2; }
.box { width: 32px; height: 32px; margin: 4px; padding: 6px; border: 2px solid #1565c0; }
Flexbox is a one-dimensional layout method for arranging items in rows or columns. Key properties include:
<div class="flex-demo">
<div class="box">1</div>
<div class="box">2</div>
<!-- repeat for 23 boxes -->
</div>
.flex-demo {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
CSS Grid is a two-dimensional layout system for creating complex layouts. Key properties include:
<div class="grid-demo">
<div class="box">1</div>
<div class="box">2</div>
<!-- repeat for 23 boxes -->
</div>
.grid-demo {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 8px;
}
Vanilla JavaScript manipulates the DOM directly with methods like querySelector and addEventListener. React lets you describe the UI declaratively with components and state, and it updates the DOM efficiently when state changes.
| Dependency | Runs when... |
|---|---|
[] |
Only once after mount |
[count] |
Whenever count changes |
[user] |
Whenever context/state reference changes |
| No dependency array | After EVERY render |
| Action | Re-render? |
|---|---|
| setState() | β Yes |
| dispatch() | β Yes |
| Context Provider changes | β Yes |
| Props change | β Yes |
| useEffect() | β No* |
* Unless the effect itself calls
setState().
Use useEffect for side effects such as fetching data, subscribing to events, timers, or syncing with browser APIs like localStorage. It is usually not the right tool for computing values from existing state during render.
| Context | Reducer |
|---|---|
| Shares state | Updates state |
| Avoids prop drilling | Centralizes logic |
| Who can access? | How does it change? |
A parent component can own state and pass both values and callback functions to children through props. This is a common pattern for controlling behavior from a parent.
function Parent() {
const [count, setCount] = useState(0);
const handleReset = () => setCount(0);
return (
Count: {count}
);
}
function Child({ count, onReset }) {
return ;
}
| Class Component | Functional Component |
|---|---|
| Uses lifecycle methods | Uses hooks |
| Has this.state and this.setState() | Uses useState() hook |
| More boilerplate code | Simpler and more concise |
useContext lets a component read values from a context without passing props through every level. It is helpful for shared data such as themes, authentication, or user settings.
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
{children}
);
}
function Header() {
const { theme } = useContext(ThemeContext);
return Current theme: {theme}
;
}
Angular supports several binding types:
{{ value }}[src]="imageUrl"(click)="save()"[(ngModel)]@Component({
template: `<h2>{{ title }}</h2>`
})
export class DemoComponent {
title = 'Angular';
}
Services centralize reusable logic and are injected into components via Angular's DI container.
@Injectable({ providedIn: 'root' })
export class UserService {
getUsers() { return ['Ada', 'Grace']; }
}
RxJS lets Angular handle asynchronous streams with observables, operators, and subscriptions.
this.http.get<User[]>('/api/users').subscribe(users => {
this.users = users;
});
Angular updates the UI based on change detection. Using ChangeDetectionStrategy.OnPush can improve performance by limiting checks.
@Component({
selector: 'app-card',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '{{ name }}
'
})
export class CardComponent { @Input() name = ''; }
The Node.js event loop is a mechanism that allows Node.js to perform non-blocking I/O operations by offloading operations to the system kernel whenever possible.
Node.js uses the CommonJS module system, where each file is treated as a separate module.
import and export, but it requires the use of the .mjs extension or setting "type": "module" in package.json.Streams are a way to handle reading/writing data in chunks, which is efficient for large data sets.