this, call, apply, and bind

this is determined by a function's call site, not where it's defined; call/apply/bind set it explicitly, and arrow functions have no this of their own.

                fn.call(thisArg, ...args) / fn.apply(thisArg, argsArray) / fn.bind(thisArg)
              

Purpose

this is determined by how a function is called (the “call site”), not by where it’s defined. call, apply, and bind each set this explicitly; arrow functions instead inherit this from their enclosing lexical scope, having none of their own.

Syntax

const counter = { count: 0 };

function increment(step) {
  this.count += step;
}

increment.call(counter, 1); // this = counter, args passed individually
increment.apply(counter, [1]); // this = counter, args passed as an array
const bound = increment.bind(counter); // returns a new function, this permanently counter
bound(5);

Behavior notes

Call style Example this is
Method call obj.method() obj — whatever precedes the dot
Plain call someFunction() undefined in strict mode/modules
Constructor call new SomeClass() The newly created instance
Explicit binding fn.call(obj) / .apply(obj) / .bind(obj) obj, set explicitly
Arrow function () => {} Inherited from the enclosing lexical scope — no this of its own
  • call and apply invoke the function immediately with the given this; bind instead returns a new function with this permanently fixed, callable later.
  • Detaching a method from its object (const fn = obj.method;) loses the method-call this — the detached function is just a plain function now, called however its new call site determines.
  • Arrow functions cannot have their this changed by call/apply/bind at all — the thisArg argument is simply ignored for them.

Common mistakes

  • Passing a method as a bare callback (element.addEventListener('click', obj.method)) and being surprised this isn’t obj inside it — the detachment loses the method-call binding. bind it, or use an arrow function wrapper, to preserve it.
  • Assuming an arrow function method on an object literal gets that object as this — it doesn’t; an arrow function used as an object property still has no this of its own and looks outward to whatever scope the object literal itself was written in.

Runtime notes

Core ECMAScript, identical behavior across every current browser and Node version.

Taught in these lessons

Related reference