Execution Context in JavaScript - Exercise 3
These methods explicitly choose the receiver for a regular function call; bind returns a new function.
function introduce() {
return `${this.name} is ready`;
}
const user = { name: 'Ava' };
console.log(introduce.call(user));
console.log(introduce.bind(user)());Arrow functions capture this from their surrounding lexical environment and ignore replacement by call, apply, or bind.
const user = {
name: 'Mina',
show: () => this.name
};
console.log(user.show()); // not user.nameA constructor call creates a new object, sets its prototype, and calls the constructor with this bound to that new object.
function User(name) {
this.name = name;
}
const user = new User('Sam');
console.log(user.name);Each recursive call gets a new context with its own parameters and local bindings on the call stack.
function factorial(number) {
if (number <= 1) return 1;
return number * factorial(number - 1);
}
console.log(factorial(3));
// contexts: factorial(3) -> factorial(2) -> factorial(1)Modules have their own module environment, do not attach top-level bindings to window, and use undefined for top-level this.
// main.js loaded with type="module"
const secret = 'private';
console.log(this); // undefined
// secret is not a window property.A stack trace lists the active function calls, helping you locate the path that led to an error.
function load() {
validate();
}
function validate() {
console.trace('validation path');
}
load();Unbounded recursion creates contexts faster than they can return, exhausting the call stack.
function walk() {
walk();
}
// walk(); // RangeError: Maximum call stack size exceededA closure preserves access to an outer environment after its original function context has returned.
function makeIdGenerator() {
let id = 0;
return () => ++id;
}
const nextId = makeIdGenerator();
console.log(nextId(), nextId());