Master JavaScript through hands-on coding challenges. Write real code, get instant feedback, and build practical web development skills.
Create custom iterables, stream async data with async generators, and intercept operations with Proxy/Reflect.
Symbol.iterator.
function* that yields a few values and then returns.function* idGenerator() {
yield 1;
yield 2;
yield 3;
return 4; // not iterated by for...of
}
const g = idGenerator();
console.log(g.next()); // { value: 1, done: false }
console.log(g.next()); // { value: 2, done: false }for...of and via manual next() calls.for (const n of idGenerator()) {
console.log(n); // 1, 2, 3
}
const it = idGenerator();
console.log(it.next().value); // 1[Symbol.iterator]() and returns an iterator with next().
const range = (start, end) => ({
start, end,
[Symbol.iterator]() {
let cur = this.start;
return {
next: () => ({ value: cur, done: cur++ > end })
};
}
});
console.log([...range(1, 5)]); // [1,2,3,4,5]yield* to compose generators.function* letters() { yield* ['A', 'B', 'C']; }
for (const ch of letters()) console.log(ch); // A B Creturn() and observe done: true.
const gen = idGenerator();
console.log(gen.return('stop')); // { value: 'stop', done: true }[...generator].
function* gen(){ yield 1; } then gen().next()[Symbol.iterator]() returning an object with next()yield* to another iterable[...gen()]Review feedback below
async function*, consume with for await...of, and implement Symbol.asyncIterator.
async function* that awaits between yields.
const delay = (ms) => new Promise(r => setTimeout(r, ms));
async function* asyncCounter(max) {
for (let i = 1; i <= max; i++) {
await delay(100);
yield i;
}
}(async () => {
for await (const n of asyncCounter(3)) {
console.log('n =', n);
}
})();next() and await its result.
(async () => {
const it = asyncCounter(2);
console.log(await it.next()); // { value: 1, done: false }
})();[Symbol.asyncIterator]().
const asyncRange = (start, end, step = 1) => ({
start, end, step,
async *[Symbol.asyncIterator]() {
for (let v = this.start; v <= this.end; v += this.step) {
await delay(50);
yield v;
}
}
});try/catch.
async function* risky() {
try { yield 1; throw new Error('boom'); }
catch (e) { yield 'handled:' + e.message; }
}for await (const v of asyncRange(...)).
async function* gen(){ await x; yield y; }for await (const x of gen()) { ... }[Symbol.asyncIterator]()await iterator.next()try/catch for error handlingReview feedback below
Proxy and use Reflect to forward operations safely.
const target = { role: 'user' };
const handler = {
get(target, prop, receiver) {
console.log('get', prop);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
console.log('set', prop, value);
return Reflect.set(target, prop, value, receiver);
}
};
const user = new Proxy(target, handler);
user.name = 'Alice';
console.log(user.name);set (e.g., ensure age is a number) and block invalid data.
const validator = {
set(obj, prop, value) {
if (prop === 'age' && typeof value !== 'number') throw new TypeError('age must be number');
return Reflect.set(obj, prop, value);
}
};
const safeUser = new Proxy({}, validator);
// safeUser.age = 'x' // throwshas trap and delete with deleteProperty.
const audit = {
has(t, p) { console.log('has', p); return Reflect.has(t, p); },
deleteProperty(t, p) { console.log('delete', p); return Reflect.deleteProperty(t, p); }
};
const audited = new Proxy({ a: 1 }, audit);
console.log('a' in audited);
delete audited.a;apply) or a constructor (construct).
function sum(a, b) { return a + b; }
const fnProxy = new Proxy(sum, {
apply(target, thisArg, args) {
console.log('apply', args);
return Reflect.apply(target, thisArg, args);
}
});
console.log(fnProxy(2, 3)); // 5revoke().
const { proxy, revoke } = Proxy.revocable({ x: 1 }, {});
console.log(proxy.x); // 1
revoke();
try { console.log(proxy.x); } catch (e) { console.log('revoked'); }get, set, has, deleteProperty) inside traps.
new Proxy(target, handler) with trapsset, forward with Reflect.set()in with has(), deletes with deleteProperty()apply; constructors: trap constructProxy.revocable(target, handler)Review feedback below