The JavaScript this keyword does not mean "the object where the function was written". An ordinary function usually gets its receiver from the call site; an arrow inherits this from its surrounding scope. Strict-mode traces are more reliable than loose definitions. Use the broader programming tutorial path and explore the free coding courses.
What this means when a function runs
this is the receiver supplied to the current invocation. An ordinary function can receive different values at different call sites. An arrow has no this of its own and closes over the surrounding value.
Snippets use strict mode. A plain ordinary-function call then supplies undefined as this. Non-strict scripts and host environments can differ, so "it is always window" is unsafe.
'use strict';
const box = {
value: 6,
read() { return this.value; }
};
box.read(); // 6
const read = box.read;
read(); // TypeErrorbox.read() selects box and returns 6. Detached read() is a plain call: this is undefined, so reading .value throws a TypeError.
Five call patterns that decide the receiver
Read the syntax immediately left of the parentheses.
Call expression | Rule | Receiver | Result |
|---|---|---|---|
| Plain call |
|
|
| Implicit method call |
|
|
| Explicit call | Supplied object |
|
| Constructor call | New instance |
|
| Bound function creation | Permanently | Later call returns |
The constructor row uses:
'use strict';
function Meter(start) { this.value = start; }
const meter = new Meter(7);new creates an object, supplies it as this, assigns meter.value = 7, and returns it because the constructor returns no other object.
A bound function ignores a later .call(...) receiver. If it is constructable and invoked with new, however, the fresh object becomes this.
Worked example: one account through five call sites
Follow this program in order:
'use strict';
const account = {
owner: 'Asha',
balance: 1200,
deposit(amount) {
this.balance += amount;
return `${this.owner}:${this.balance}`;
}
};
account.deposit(300); // 'Asha:1500'
const detached = account.deposit;
detached(200); // TypeError; balance stays 1500
detached.call(account, 200); // 'Asha:1700'
const boundDeposit = detached.bind(account);
boundDeposit(100); // 'Asha:1800'
boundDeposit.call({ owner: 'Dev', balance: 5 }, 50);
// 'Asha:1850'Trace expression, receiver, old balance, amount, and result:
Expression | Selected receiver | Old balance | Amount | Result |
|---|---|---|---|---|
|
| 1200 | 300 |
|
|
| account stays at 1500 | 200 |
|
|
| 1500 | 200 |
|
| bound | 1700 | 100 |
|
| bound | 1800 | 50 |
|
The failure does not change account.balance, so the next call starts at 1500, not 1700. Debug by asking, "What exact expression invoked this function?" not only where it was declared.

Arrow functions, callbacks, and object-literal traps
Compare regular and arrow callbacks:
'use strict';
const scoreboard = {
points: 10,
bonuses: [2, 5],
totalsWrong() {
return this.bonuses.map(function (bonus) {
return this.points + bonus;
});
},
totalsRight() {
return this.bonuses.map((bonus) => this.points + bonus);
}
};totalsWrong() throws because map invokes the regular callback without scoreboard. totalsRight() returns [12, 15]: its arrow inherits this and computes 10 + 2 = 12, then 10 + 5 = 15.
A regular callback works when map receives a thisArg:
return this.bonuses.map(function (bonus) {
return this.points + bonus;
}, this); // [12, 15]An arrow is not an object-method shortcut:
function makeCard() {
'use strict';
return {
label: 'JS',
regular() { return this.label; },
arrow: () => this?.label
};
}
const card = makeCard();
card.regular(); // 'JS'
card.arrow(); // undefinedThe regular method receives card. The arrow captured the factory's strict-mode undefined, not card. Retaining context is useful when you move from JavaScript callbacks into component state.
![Two callback lanes: a regular map callback that throws versus an arrow callback that inherits scoreboard and returns [12, 15].](https://cdn.knowledgegate.ai/blog-assets/blog_asset_1784537551655_z7tmcm.jpg)
Common this mistakes and their repairs
A detached or destructured method loses its receiver: const { deposit } = account; deposit(25) throws. Repair it with const depositForAsha = account.deposit.bind(account) or (amount) => account.deposit(amount). The fix preserves a call site, not a variable name.
Method callbacks have the same problem:
'use strict';
const wallet = {
balance: 40,
add(x) { this.balance += x; return this.balance; }
};
const invoke = (fn) => fn(25);
invoke(wallet.add); // TypeError
invoke((amount) => wallet.add(amount)); // 65The repair leaves wallet.balance === 65. Use arrows to retain a surrounding receiver, not where callers must select one with method syntax, .call, .apply, or .bind.
How tracing and interview questions test this
This is common JavaScript tracing and interview practice, not an official pattern for a named exam. Connect it with callbacks during web-technology revision. Named exam patterns require that exam's current official notice.
'use strict';
const lookup = { value: 4, get() { return this.value; } };
const other = { value: 9 };
lookup.get.call(other); // 9
const fixed = lookup.get.bind(lookup);
fixed.call(other); // 4The first call selects other. Binding then fixes lookup, so .call(other) cannot replace it. Solve in three passes: mark arrows, classify other calls as plain, method, explicit, constructor, or bound, then compute. Name the receiver before the output.
Three exercises with answers
const team = { score: 8, add(x) { return this.score + x; } }; const add = team.add.bind({ score: 20 }); add(3);Answer:
23. The bound receiver hasscore = 20;team.scoreis irrelevant.const box = { base: 6, nums: [1, 4], totals() { return this.nums.map(function (n) { return this.base + n; }); } };Answer: Change the callback to
(n) => this.base + n. Thenbox.totals()returns[7, 10], from6 + 1and6 + 4.function Point(x, y) { this.x = x; this.y = y; } const p = new Point(2, 5); p.x + p.y;Answer:
7.newcreatesp, supplies it asthis, and stores2and5on the object.
Short version and the next practical step
Ordinary functions inspect the call site.
Arrows inherit
thisfrom the surrounding scope.Detached methods lose their receiver.
.calland.applysupply one call's receiver..bindcreates a reusable bound function. With a constructable bound function,newstill constructs a fresh receiver.
Rerun the account example with a starting balance of 2400 and a first deposit of 600. The successful balances become 3000, 3200, 3300, and 3350; the detached call still fails and changes nothing.
Now practise these rules in a complete JavaScript learning path. Predict each receiver on paper, run the snippet, then explain every mismatch from the call site.




