HuntExams Academy logo
JavaScriptIntermediate#this#functions

How does 'this' work in JavaScript?

Answer

In a normal function 'this' is decided by the call site: the object before the dot, undefined in strict mode standalone calls, the new instance with new, or an explicit value with call/apply/bind. Arrow functions capture 'this' lexically instead.

Example

const obj = {
  name: 'A',
  regular() { return this.name; },
  arrow: () => this?.name,
};
obj.regular(); // 'A'
obj.arrow();   // undefined

Detailed explanation

In JavaScript, `this` is a value available inside functions whose meaning usually depends on how the function is invoked, not where it was defined. For normal functions, inspect the call site first. In `obj.regular()`, the property call makes `obj` the receiver, so `this.name` reads `'A'`. However, `const fn = obj.regular; fn();` loses that receiver. JavaScript does not permanently attach a method to its object merely because the function is stored as an object property.

For a standalone normal-function call, `this` is `undefined` if the function executes in strict mode. In non-strict mode, it defaults to `globalThis`. With `fn.call(value, arg)` or `fn.apply(value, [arg])`, the caller supplies `this` explicitly; the difference is how arguments are passed. `fn.bind(value)` creates a new function with a fixed receiver for ordinary calls. Non-strict functions replace explicit `null` or `undefined` receivers with the global object and box primitive receivers; strict functions preserve the supplied value.

Calling a constructible function with `new` creates an object, links it to the constructor's prototype, and runs the constructor with that object as `this`. Normally, that object becomes the result, although an explicitly returned object can replace it. When a bound constructor is invoked with `new`, its bound receiver is ignored in favour of the new instance. These rules matter when debugging methods passed as callbacks: the receiving API determines how a normal callback is invoked, so its original object context may disappear.

Arrow functions have no own `this`; they resolve it through their enclosing lexical environment. Consequently, `call`, `apply`, and `bind` cannot change an arrow's receiver, and arrows cannot be constructors. In the example, the object literal does not establish a `this` scope, so `obj.arrow()` uses the surrounding `this`, not `obj`. Its result is not universally `undefined`: `this?.name` depends on the surrounding environment and any existing `name` property. Interviewers look for this distinction and expect you to explain both method extraction and environment-dependent arrow behaviour.

Key points to remember

  • Normal-function `this` is determined by invocation, not by where the function is stored.
  • `obj.method()` supplies `obj` as the receiver; extracting the method loses that receiver.
  • Standalone calls use `undefined` in strict functions and `globalThis` in non-strict functions.
  • `call` and `apply` invoke with an explicit receiver; `bind` returns a bound function; `new` supplies a new instance.
  • Arrows capture lexical `this`; object literals do not create a new `this` scope.

Common mistakes candidates make

  • Assuming a function stored on an object always uses that object as `this`, even when passed as a callback.
  • Using an arrow for an object method that needs the receiver, or trying to change its `this` with `bind`.
  • Claiming the example's arrow always returns `undefined` without checking its enclosing environment.

Likely follow-up questions

How can you preserve `this` when passing a method as a callback?

Use `obj.method.bind(obj)` or a wrapper such as `() => obj.method()`. The bound function fixes the receiver, while the wrapper performs a property call when invoked.

What is top-level `this`?

In an ES module, top-level `this` is `undefined`; in a browser's classic script, it is the global `this` value, normally `window`. In a Node.js CommonJS module, it is `module.exports`, so top-level arrows behave differently across these environments.

Why does an arrow inside a class method often work well as a callback?

It captures the `this` of that method invocation, so it retains the instance when the enclosing method was called on the instance. It does not acquire a different receiver when another API invokes the callback.

Interview tip: Explain the call-site rules first, contrast arrows with normal functions, and demonstrate receiver loss with an extracted method.

Related Interview Questions

1
JavaScriptIntermediate#functions#this

Difference between call, apply and bind?

Open
2
JavaScriptIntermediate#functions#es6

Difference between arrow functions and regular functions?

Open
3
JavaScriptIntermediate#prototypes#oop

What is prototypal inheritance?

Open