40 Advanced JavaScript Tutorials
1. Advanced Prototypes
Prototypes can be dynamically modified to extend object behavior.
Example: Dynamic prototype modification.
function Animal() {}
Animal.prototype.speak = function() { return "Sound"; };
const dog = new Animal();
Animal.prototype.speak = function() { return "Woof"; };
console.log(dog.speak());
Note: Changes to prototypes affect all instances.
2. Metaprogramming
Metaprogramming manipulates code behavior dynamically.
Example: Dynamic method addition.
const obj = {};
Object.defineProperty(obj, "sayHi", {
value: () => "Hello!",
enumerable: false
});
console.log(obj.sayHi());
Note: Use Object.defineProperty for fine-grained control.
3. Symbol Types
Symbols create unique, non-enumerable properties.
Example: Using Symbol.
const sym = Symbol("id");
const obj = { [sym]: 123 };
console.log(obj[sym]);
Note: Symbols prevent property name collisions.
4. Reflect API
Reflect API provides methods for object manipulation.
Example: Using Reflect.
const obj = {};
Reflect.set(obj, "name", "Alice");
console.log(Reflect.get(obj, "name"));
Note: Reflect methods align with Proxy traps.
5. Advanced Generators
Generators can yield control to other generators.
Example: Delegating generator.
function* subGen() { yield 1; yield 2; }
function* mainGen() { yield* subGen(); yield 3; }
const gen = mainGen();
console.log([...gen]);
Note: Use yield* for delegation.
6. Async Iterators
Async iterators handle asynchronous iteration.
Example: Async iterator.
const asyncIterable = {
async *[Symbol.asyncIterator]() {
await new Promise(r => setTimeout(r, 1000));
yield 1;
}
};
(async () => {
for await (const value of asyncIterable) {
console.log(value);
}
})();
Note: Use with for await...of.
7. Proxy Traps
Proxy traps customize object operations like property access.
Example: Custom getter trap.
const handler = {
get(target, prop) {
return prop in target ? target[prop] : "Missing";
}
};
const proxy = new Proxy({ name: "Alice" }, handler);
console.log(proxy.name, proxy.age);
Note: Traps include set, deleteProperty, etc.
8. Advanced Promises
Advanced Promise patterns handle complex async flows.
Example: Promise.allSettled.
const promises = [
Promise.resolve(1),
Promise.reject("Error"),
Promise.resolve(3)
];
Promise.allSettled(promises).then(results => console.log(results));
Note: allSettled waits for all promises.
9. Microtask Queue
Microtasks execute before macrotasks in the event loop.
Example: Microtask vs macrotask.
setTimeout(() => console.log("Macrotask"), 0);
Promise.resolve().then(() => console.log("Microtask"));
Note: Microtasks have higher priority.
10. WebAssembly Basics
WebAssembly runs high-performance code in the browser.
Example: Loading WebAssembly (simulated).
WebAssembly.instantiateStreaming(fetch("module.wasm")).then(result => {
console.log(result.instance.exports.add(2, 3));
});
Note: Requires a .wasm file.
11. SharedArrayBuffer
SharedArrayBuffer enables shared memory between threads.
Example: Shared memory.
const sab = new SharedArrayBuffer(4);
const arr = new Int32Array(sab);
arr[0] = 42;
console.log(arr[0]);
Note: Requires cross-origin isolation.
12. Atomics
Atomics provide atomic operations for SharedArrayBuffer.
Example: Atomic operation.
const sab = new SharedArrayBuffer(4);
const arr = new Int32Array(sab);
Atomics.store(arr, 0, 100);
console.log(Atomics.load(arr, 0));
Note: Prevents race conditions in shared memory.
13. Advanced Event Loop
Advanced event loop techniques manage complex async tasks.
Example: Microtask scheduling.
queueMicrotask(() => console.log("Microtask"));
setTimeout(() => console.log("Macrotask"), 0);
Note: queueMicrotask schedules microtasks directly.
14. Performance Optimization
Optimizations reduce runtime and memory usage.
Example: Efficient loop.
const arr = new Array(1000).fill(1);
const start = performance.now();
arr.forEach(n => n * 2);
console.log(performance.now() - start);
Note: Use for loops for better performance in some cases.
15. Memory Management
Memory management minimizes leaks and optimizes usage.
Example: Avoiding memory leaks.
let obj = { data: new Array(1000000) };
obj = null; // Allow garbage collection
console.log("Memory freed");
Note: Set unused references to null.
16. Advanced Web Workers
Web Workers can handle complex computations off the main thread.
Example: Worker with message passing.
const worker = new Worker(URL.createObjectURL(new Blob(["onmessage = e => postMessage(e.data.map(n => n * 2));"])));
worker.postMessage([1, 2, 3]);
worker.onmessage = e => console.log(e.data);
Note: Workers improve performance for heavy tasks.
17. Service Worker Strategies
Service Workers implement caching strategies for offline support.
Example: Cache-first strategy (simulated).
self.addEventListener("fetch", e => {
e.respondWith(caches.match(e.request).then(response => response || fetch(e.request)));
});
Note: Use cache.addAll for pre-caching.
18. Advanced IndexedDB
IndexedDB supports transactions and indexing.
Example: IndexedDB with index (simulated).
const request = indexedDB.open("db");
request.onupgradeneeded = () => {
const db = request.result;
const store = db.createObjectStore("store", { keyPath: "id" });
store.createIndex("name", "name");
};
request.onsuccess = () => console.log("DB ready");
Note: Indexes improve query performance.
19. WebRTC Basics
WebRTC enables real-time peer-to-peer communication.
Example: RTC connection (simulated).
const pc = new RTCPeerConnection();
pc.onicecandidate = e => console.log(e.candidate);
pc.createOffer().then(offer => pc.setLocalDescription(offer));
Note: Requires signaling server for production.
20. WebSocket Scaling
WebSocket scaling handles multiple client connections.
Example: WebSocket reconnection (simulated).
function connect() {
const ws = new WebSocket("ws://example.com");
ws.onclose = () => setTimeout(connect, 1000);
ws.onmessage = e => console.log(e.data);
}
connect();
Note: Implement reconnection logic for reliability.
21. Custom Elements
Custom Elements create reusable HTML elements.
Example: Defining a custom element.
class MyElement extends HTMLElement {
connectedCallback() {
this.innerHTML = "Hello from custom element!";
}
}
customElements.define("my-element", MyElement);
Note: Extends HTMLElement.
22. Shadow DOM
Shadow DOM encapsulates DOM and styles.
Example: Creating shadow DOM.
class MyComponent extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "open" });
shadow.innerHTML = "Shadow content
";
}
}
customElements.define("my-component", MyComponent);
Note: Use mode: "closed" for private DOM.
23. Advanced Observers
Observers like PerformanceObserver monitor performance metrics.
Example: PerformanceObserver.
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => console.log(entry.name));
});
observer.observe({ type: "mark" });
performance.mark("test");
Note: Tracks various performance entries.
24. Functional Reactive
Functional reactive programming manages data streams.
Example: Simple stream (simulated).
function fromEvent(element, event) {
return {
subscribe: callback => element.addEventListener(event, callback)
};
}
fromEvent(document, "click").subscribe(() => console.log("Clicked"));
Note: Libraries like RxJS enhance this pattern.
25. Advanced Currying
Advanced currying creates flexible, reusable functions.
Example: Infinite currying.
function curry(fn) {
return function curried(...args) {
return args.length >= fn.length ? fn(...args) : (...more) => curried(...args, ...more);
};
}
const sum = curry((...args) => args.reduce((a, b) => a + b, 0));
console.log(sum(1)(2)(3)());
Note: Allows partial application indefinitely.
26. Transducers
Transducers transform data in a composable way.
Example: Simple transducer.
const map = fn => reducer => (acc, val) => reducer(acc, fn(val));
const filter = pred => reducer => (acc, val) => pred(val) ? reducer(acc, val) : acc;
const transducer = map(x => x * 2);
console.log([1, 2, 3].reduce(transducer((a, b) => a + b), 0));
Note: Reduces memory usage in pipelines.
27. Lazy Evaluation
Lazy evaluation defers computation until needed.
Example: Lazy sequence.
function* lazyRange(n) {
for (let i = 0; i < n; i++) yield i;
}
const range = lazyRange(1000);
console.log(range.next().value);
Note: Saves memory for large datasets.
28. Advanced Memoization
Advanced memoization handles complex inputs.
Example: Memoizing recursive function.
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
};
}
const fib = memoize(n => n <= 1 ? n : fib(n - 1) + fib(n - 2));
console.log(fib(10));
Note: Cache complex keys with serialization.
29. Monads
Monads encapsulate computations with context.
Example: Maybe monad.
class Maybe {
constructor(value) { this.value = value; }
static of(value) { return new Maybe(value); }
map(fn) { return this.value == null ? this : Maybe.of(fn(this.value)); }
}
const result = Maybe.of(5).map(x => x * 2);
console.log(result.value);
Note: Monads chain operations safely.
30. Functors
Functors map functions over wrapped values.
Example: Simple functor.
class Functor {
constructor(value) { this.value = value; }
static of(value) { return new Functor(value); }
map(fn) { return Functor.of(fn(this.value)); }
}
console.log(Functor.of(5).map(x => x * 2).value);
Note: Functors preserve structure during mapping.
31. Advanced Modules
Advanced modules use dynamic imports and top-level await.
Example: Top-level await (simulated).
const module = await import("./module.js");
console.log(module.default());
Note: Requires module script type.
32. Tree Shaking
Tree shaking eliminates unused module code.
Example: Exporting used function (simulated).
export function used() { return "Used"; }
export function unused() { return "Unused"; }
import { used } from "./module.js";
console.log(used());
Note: Requires ES modules and bundlers.
33. Code Splitting
Code splitting divides code into smaller bundles.
Example: Dynamic import for splitting.
import("./module.js").then(module => console.log(module.default()));
Note: Improves initial load time.
34. Advanced Regex
Advanced regex uses lookaheads and lookbehinds.
Example: Positive lookahead.
const regex = /(?=\d{4})\w+/;
console.log("1234abc".match(regex));
Note: Lookaheads assert conditions without consuming.
35. Intl Advanced
Intl API supports advanced formatting like plurals.
Example: Plural rules.
const pr = new Intl.PluralRules("en-US");
console.log(pr.select(1), pr.select(2));
Note: Useful for i18n applications.
36. Typed Array Buffers
Typed arrays with ArrayBuffer manipulate raw binary data.
Example: DataView manipulation.
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
view.setInt32(0, 42);
console.log(view.getInt32(0));
Note: DataView provides flexible access.
37. BigInt Advanced
BigInt handles arbitrary-precision arithmetic.
Example: Large number operations.
const a = 12345678901234567890n;
const b = BigInt(Number.MAX_SAFE_INTEGER);
console.log(a * b);
Note: Avoid mixing with regular numbers.
38. SIMD Operations
SIMD (Single Instruction, Multiple Data) optimizes parallel computations (simulated).
Example: SIMD vector addition (simulated).
const vec1 = new Float32Array([1, 2, 3, 4]);
const vec2 = new Float32Array([5, 6, 7, 8]);
const result = vec1.map((v, i) => v + vec2[i]);
console.log(result);
Note: Native SIMD requires WebAssembly.
39. Advanced Error Handling
Advanced error handling uses custom error classes.
Example: Custom error.
class CustomError extends Error {
constructor(message) { super(message); this.name = "CustomError"; }
}
try {
throw new CustomError("Test error");
} catch (e) {
console.log(e.name, e.message);
}
Note: Extend Error for specific cases.
40. Micro-Frontends
Micro-frontends split frontend into independent components.
Example: Loading micro-frontend (simulated).
function loadMicroFrontend(url) {
const script = document.createElement("script");
script.src = url;
document.body.appendChild(script);
}
loadMicroFrontend("microfrontend.js");
Note: Use module federation for real implementations.