iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Function Invocation

A function can be called in four ways — and each binds this differently. That single fact explains 80% of "why is this undefined?" questions.

The four call types

How you call itthis becomes…
fn()undefined (strict) / window (sloppy)
obj.fn()The object before the dot — obj
new Fn()A brand-new empty object
fn.call(x) / .apply(x, args) / .bind(x)()Whatever you pass

Method extraction trap

JS
const user = {
  name: "Ada",
  greet() { return `Hi, ${this.name}!`; },
};

user.greet();                     // "Hi, Ada!" — method call, this is user

const g = user.greet;
g();                              // "Hi, undefined!" — plain call, this is lost

setTimeout(user.greet, 100);      // same problem — the callback is called plain

Three fixes

JS
// 1. Bind a permanent this
setTimeout(user.greet.bind(user), 100);

// 2. Wrapper preserves the call site
setTimeout(() => user.greet(), 100);

// 3. Class field as an arrow — auto-bound
class Toggle {
  isOn = false;
  toggle = () => this.isOn = !this.isOn;   // safe to pass around
}

Constructor calls

JS
function Counter() { this.value = 0; }
new Counter();              // { value: 0 }
Counter();                  // ⚠ this is undefined / window → bug

class Modern {}
Modern();                   // TypeError — classes refuse plain calls (helpful!)
Tip: If you ever pass a method as a callback, either bind it or wrap it in an arrow. Modern frameworks (React with class components, vanilla event listeners) hit this exact issue all the time.

Example

Example
<!DOCTYPE html>
<html>
<body>

<p id="out"></p>

<script>
document.getElementById("out").textContent = "Hello from Function Invocation!";
</script>

</body>
</html>
Try it Yourself »

Exercise

Permanently lock greet's `this` to the user object.

const greet = user.greet. (user);

Test yourself

Q1. In `obj.fn()` the value of `this` is…
Q2. A method passed as a callback usually loses…
Q3. Best modern fix for "lost this" is…

Discussion

Loading…