this binding
The this binding is the value that the this keyword refers to during one function call, which JavaScript sets from how the function was called rather than from where it was defined. Each kind of call picks it with a different rule:
The this keyword only reads the binding. The call decides it. In a method call such as user.greet(), the binding is the object before the dot, called the receiver. A call with new binds the newly created object. The .call(), .apply(), and .bind() methods of Function set the binding explicitly, and a function made with .bind() keeps it for every later call.
A plain call such as greet() has no receiver. In strict mode, which covers all class bodies and ES modules, the binding is undefined. In sloppy mode, which is any code that isn’t strict, JavaScript substitutes globalThis for a missing receiver and wraps a primitive receiver in an object.
Arrow functions don’t get a binding of their own. They use the this of the surrounding code, and .call() or .bind() can’t change it. ECMA-262 tracks this in each function’s [[ThisMode]] internal slot, which is lexical for arrow functions and strict or global for the rest.
The rules cause the most surprises when a method is passed as a callback. Passing user.greet hands over the function alone, so the code that calls it later usually makes a plain call and the object is lost.
Example
Say a checkout page formats a list of prices with a method on a Formatter instance and hands that method to an array’s .map() call:
> class Formatter {
… constructor(currency) {
… this.currency = currency;
… }
… format(amount) {
… return `${amount.toFixed(2)} ${this.currency}`;
… }
… }
undefined
> const formatter = new Formatter("EUR");
undefined
> formatter.format(5)
'5.00 EUR'
> try {
… [5, 12.5].map(formatter.format);
… } catch (error) {
… error.message;
… }
"Cannot read properties of undefined (reading 'currency')"
> [5, 12.5].map(formatter.format.bind(formatter))
[ '5.00 EUR', '12.50 EUR' ]
> [5, 12.5].map((amount) => formatter.format(amount))
[ '5.00 EUR', '12.50 EUR' ]
The direct call binds this to formatter. Inside .map(), the same function runs as a plain call, and because class code is strict, the binding is undefined. The bound copy carries formatter with it, and the arrow function restores the method call, so both versions find this.currency.
Related Resources
Have a question about this? Mentor AI can show you examples, compare related terms, and point you to tutorials.
By Leodanis Pozo Ramos • Updated Nov. 5, 2026