Declare variables
const x = 1let n = 0const can't be reassignedvar x = 1Function-scopedTraplet and const are hoisted, but can't be read until their line runs. That gap is the temporal dead zone.
this is set by how a function is called, not where it's written. Arrow functions take this from the code around them.null..then callback beats a zero-delay setTimeout.const x = 1let n = 0const can't be reassignedvar x = 1Function-scopedTraplet and const are hoisted, but can't be read until their line runs. That gap is the temporal dead zone.
typeof xArray.isArray(x) Traptypeof null and typeof [] both give "object".
123nCan't mix with numbersTipBinary floats can't store 0.1 exactly. Compare with a small tolerance, and count money in whole cents.
undefinedJavaScript sets itReferenceErrorTipnull is empty on purpose. x == null matches it and undefined. typeof is safe on undeclared names.
a === bBut 5 == "5" is true"5" + 3"5" - 3"53", then 2Trap[] and {} are truthy. if (!x) also rejects 0 and "".
function f() {}Callable before its lineconst f = () => {}Callable only after its lineTrapArrow functions have no this or arguments of their own, and new can't call them.
TrapTimers in a var loop share one i, so they all log its final value. let gives each pass its own.
obj.f()The object before the dotf()undefined in strict mode, else the global objectthis yourselff.call(o, a)f.bind(o)f.apply(o, [a])TrapA method passed as a callback loses this. Pass () => obj.f() instead.
function f(x = 1) {}Applies only to undefinedfunction f(...args) {}argumentsArray-like, and not in arrowsa => b => a + bx => f(g(x))TipA higher-order function takes or returns a function, like map or bind.
[...arr, x]{ ...obj, a: 1 }TipFunctional style keeps logic pure and data immutable. The cost is extra copies.
{ a: 1 }Object.create(proto) obj[key]Also for keys with spacesJSON.stringify(obj) JSON.parse(text) TipJSON.parse throws on bad input. stringify skips functions and undefined in objects.
{ ...obj }structuredClone(obj) JSON.parse( JSON.stringify(o) )a === bSame object onlyTrapA spread copy shares nested objects with the original.
Object.getPrototypeOf o.__proto__Trapprototype lives on the constructor. Instances link to it through __proto__ and share its methods.
class B extends A {}function A(x) { this.x = x; }new doesMakes an object, links its prototype, runs the constructorTipClasses are prototypes underneath. They need new and always run in strict mode.
#count = 0;get total() {}set total(v) {}TipObject. sets flags like writable. Any you leave out are false.
Object.preventExtensions Block new keysObject.sealAlso block deletesObject.freezeMake it read-onlyTrapAll three are shallow, so nested objects can still change.
[...new Set(arr)]new Map()Symbol("id")TrapA WeakMap drops an entry once its key object is garbage collected. You can't loop over it.
new Proxy(obj, { get })Reflect.get(t, k)arr.map(x => x * 2)arr.filter(x => x > 2)arr.reduce((a, x) => a + x, 0)arr.forEach(fn)Returns undefinedarr.slice(1, 3)arr.splice(1, 2, x)Returns what it removedTrapreduce with no start value throws on an empty array.
for (const x of arr)for (const k in obj)function* gen() {}An iterator that pauses at each yieldTrapfor...in on an array gives indexes as strings, and inherited keys too.
const [a, ...b] = arrconst { a, b = 1 } = oMath.max(...nums) a?.b?.cobj.fn?.()null or undefinedx ?? 10x || 10a && a.bTrap0 || 10 is 10, but 0 ?? 10 keeps the 0.
`Hi ${name}`tag`Hi ${name}`The tag gets the strings, then the valuesok ? "yes" : "no"fori++, j--The comma returns the last valuequeueMicrotask(fn) getData(cb)Steps nest into callback hellnew Promise((res, rej) => {})p.then(f).catch(g) TipA promise settles once. Handlers always run as microtasks.
try { await p } catch {}Promise.all(ps)Promise.allSettled(ps) TrapAwaiting independent calls one by one adds up their time.
Promise.race(ps) Promise.any(ps)AggregateError if all failAsked in interviews
AskedWhat is the difference between Promise.race() and Promise.any()?try {} catch (e) {} finally {}class E extends Error {}Set this.name in itTraptry only catches rejections you await inside it.
"use strict";with (obj) {}Banned in strict modeTipModules and classes are strict already. Strict mode makes an undeclared assignment throw.
el.querySelector(s) el.querySelectorAll(s) MutationObserver document.createElement parent.append(el) el.textContent = sel.innerHTML = sNever pass it user inputel.innerTextSlower, because it forces a layoutTipThe value attribute keeps the HTML's first value. The value property holds what the user typed.
el.addEventListener(t, fn)el.onclick = fnOnly one per evente.preventDefault() e.stopPropagation() TrappreventDefault doesn't stop bubbling, and stopPropagation doesn't cancel the default.
el.addEventListener(t, fn, true)e.target.closest("li") e.targete.currentTargetTrapEvents go down to the target, then bubble up. focus doesn't bubble, so delegation misses it.
A plain script blocks parsing. async runs as soon as it downloads. defer runs after parsing, in page order.
<script defer><script async>"DOMContentLoaded" load waits for images toolocalStorage.setItem(k, v)sessionStorageSame APIdocument.cookie = "a=1"TrapAny script can read Web Storage. Keep tokens in HttpOnly cookies.
await fetch(url)await res.json()controller.abort() AbortSignal.timeout(ms) Trapfetch resolves on a 404. Check res.ok.
loading="lazy"IntersectionObserver await import("./m.js") requestAnimationFrame new Worker("w.js")TrapWorkers can't touch the DOM. Service workers also need HTTPS, or localhost.
export const x = 1import { x } from "./m.js"require("./m.js") (function () {})()Debounce runs after the events stop. Throttle runs at the first event, then skips events until its wait ends.
TipFor deep recursion, use a loop. Only Safari optimizes tail calls.
TrapObservers that never unsubscribe leak memory.
return this;Nothing matches. Try a shorter word, or clear the search.
With Pro, you can:
Already have Pro? Sign in