Hoisting and closures
Function declarations are hoisted to the top of their scope, so they can be called before their definition:
console.log(greet("Ada")); // works even though defined below
function greet(name) { return `Hi ${name}`; }
A closure is a function that remembers variables from its outer scope even after the outer function returns:
function counter() {
let count = 0;
return () => ++count;
}
const inc = counter();
inc(); inc(); // 2 (count persists)
Closures power modules, memoization, and state isolation.
this binding
The value of this depends on how a function is called. Regular functions get this from the call site; arrow functions capture this lexically from where they are written:
const obj = {
name: "Ada",
label() { return this.name; }, // 'obj'
arrow: () => this.name // outer this, not obj
};
Use arrow functions for callbacks (like setTimeout or array methods) where you want to preserve the surrounding this.