Understand how JavaScript's 'this' keyword works with runnable examples. Method calls, standalone functions, arrow functions, bind/call/apply, and event handlers.
The value of 'this' in JavaScript is determined by how a function is called, not where it's defined. There are four call patterns, each producing a different 'this': method call (this = the object), standalone call (this = undefined in strict mode, globalThis otherwise), new call (this = the new instance), and explicit call via bind/call/apply (this = the value you supplied). Arrow functions are the exception — they capture 'this' lexically from their enclosing scope and cannot be rebound.
When you call a function as a property of an object, 'this' inside the function refers to that object. Detaching the method (const f = obj.fn; f()) loses this binding.
A bare function call has no owning object. In strict mode (and modules) 'this' is undefined. In sloppy mode it defaults to globalThis (window in browsers).
fn.call(ctx, ...args) and fn.apply(ctx, argsArray) call the function immediately with 'this' set to ctx. fn.bind(ctx) returns a new function permanently bound to ctx.
Arrow functions ignore the call-time rules entirely. They use the 'this' of the scope where they were defined. This makes them perfect for callbacks inside methods — no more const self = this.
Use arrow functions for callbacks inside methods so you don't have to worry about 'this'. Use regular functions (or class methods) when you need 'this' to refer to the calling object. Use bind when you must pass a method as a callback and need 'this' preserved.
"use strict";
const user = {
name: "Alice",
greet() {
return `Hi, I'm ${this.name}`;
},
};
// Method call — this = user
console.log(user.greet());
// Detached — this = undefined (strict)
const greet = user.greet;
try {
console.log(greet());
} catch (e) {
console.log("detached:", e.message);
}
// Rebind with bind
const bound = user.greet.bind(user);
console.log(bound());
// Arrow functions capture lexically
const other = {
name: "Bob",
delayedGreet() {
setTimeout(() => {
console.log(`lexical this: ${this.name}`);
}, 0);
},
};
other.delayedGreet();
// call and apply
function introduce(prefix, suffix) {
return `${prefix} ${this.name}${suffix}`;
}
console.log(introduce.call(user, "Hello,", "!"));
console.log(introduce.apply(user, ["Hola,", "."]));
Open this example in the TryJS playground to edit and run the code instantly in your browser — no signup needed.
'this' is an implicit parameter that every non-arrow function receives. Its value depends on how the function is called: as a method (this = the object), standalone (undefined/global), with new (the new instance), or via bind/call/apply (the value you supply).
By design. Arrow functions capture 'this' from the enclosing lexical scope, so they can be used as callbacks inside methods without the classic 'this is undefined' bug. This makes them unsuitable for object methods where you need 'this' to refer to the object.
call and apply invoke the function immediately with an explicit 'this'. The only difference: call takes individual arguments, apply takes an array. bind returns a new function with 'this' permanently set — it doesn't invoke anything.
Most likely you called the function standalone (not as a method) in strict mode or inside a module. Strict mode refuses to default 'this' to globalThis. Either call it as a method, bind it explicitly, or use an arrow function to capture 'this' from the outer scope.