this - JavaScript | MDN (original) (raw)
Baseline
Widely available
The this
keyword refers to the context where a piece of code, such as a function's body, is supposed to run. Most typically, it is used in object methods, where this
refers to the object that the method is attached to, thus allowing the same method to be reused on different objects.
The value of this
in JavaScript depends on how a function is invoked (runtime binding), not how it is defined. When a regular function is invoked as a method of an object (obj.method()
), this
points to that object. When invoked as a standalone function (not attached to an object: func()
), this
typically refers to the global object (in non-strict mode) or undefined
(in strict mode). The Function.prototype.bind() method can create a function whose this
binding doesn't change, and methods Function.prototype.apply() and Function.prototype.call() can also set the this
value for a particular call.
Arrow functions differ in their handling of this
: they inherit this
from the parent scope at the time they are defined. This behavior makes arrow functions particularly useful for callbacks and preserving context. However, arrow functions do not have their own this
binding. Therefore, their this
value cannot be set by bind()
, apply()
or call()
methods, nor does it point to the current object in object methods.
Try it
const test = {
prop: 42,
func() {
return this.prop;
},
};
console.log(test.func());
// Expected output: 42
Syntax
Value
In non–strict mode, this
is always a reference to an object. In strict mode, it can be any value. For more information on how the value is determined, see the description below.
Description
The value of this
depends on in which context it appears: function, class, or global.
Function context
Inside a function, the value of this
depends on how the function is called. Think about this
as a hidden parameter of a function — just like the parameters declared in the function definition, this
is a binding that the language creates for you when the function body is evaluated.
For a regular function (not an arrow function, bound function, etc.), the value of this
is the object that the function is accessed on. In other words, if the function call is in the form obj.f()
, then this
refers to obj
. For example:
function getThis() {
return this;
}
const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };
obj1.getThis = getThis;
obj2.getThis = getThis;
console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }
console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }
Note how the function is the same, but based on how it's invoked, the value of this
is different. This is analogous to how function parameters work.
The value of this
is not the object that has the function as an own property, but the object that is used to call the function. You can prove this by calling a method of an object up in the prototype chain.
const obj3 = {
__proto__: obj1,
name: "obj3",
};
console.log(obj3.getThis()); // { name: 'obj3' }
The value of this
always changes based on how a function is called, even when the function was defined on an object at creation:
const obj4 = {
name: "obj4",
getThis() {
return this;
},
};
const obj5 = { name: "obj5" };
obj5.getThis = obj4.getThis;
console.log(obj5.getThis()); // { name: 'obj5', getThis: [Function: getThis] }
If the value that the method is accessed on is a primitive, this
will be a primitive value as well — but only if the function is in strict mode.
function getThisStrict() {
"use strict"; // Enter strict mode
return this;
}
// Only for demonstration — you should not mutate built-in prototypes
Number.prototype.getThisStrict = getThisStrict;
console.log(typeof (1).getThisStrict()); // "number"
If the function is called without being accessed on anything, this
will be undefined
— but only if the function is in strict mode.
console.log(typeof getThisStrict()); // "undefined"
In non-strict mode, a special process called this substitution ensures that the value of this
is always an object. This means:
- If a function is called with
this
set toundefined
ornull
,this
gets substituted with globalThis. - If the function is called with
this
set to a primitive value,this
gets substituted with the primitive value's wrapper object.
function getThis() {
return this;
}
// Only for demonstration — you should not mutate built-in prototypes
Number.prototype.getThis = getThis;
console.log(typeof (1).getThis()); // "object"
console.log(getThis() === globalThis); // true
In typical function calls, this
is implicitly passed like a parameter through the function's prefix (the part before the dot). You can also explicitly set the value of this
using the Function.prototype.call(), Function.prototype.apply(), or Reflect.apply() methods. Using Function.prototype.bind(), you can create a new function with a specific value of this
that doesn't change regardless of how the function is called. When using these methods, the this
substitution rules above still apply if the function is non-strict.
Callbacks
When a function is passed as a callback, the value of this
depends on how the callback is called, which is determined by the implementor of the API. Callbacks are typically called with a this
value of undefined
(calling it directly without attaching it to any object), which means if the function is non–strict, the value of this
is the global object (globalThis). This is the case for iterative array methods, the Promise() constructor, etc.
function logThis() {
"use strict";
console.log(this);
}
[1, 2, 3].forEach(logThis); // undefined, undefined, undefined
Some APIs allow you to set a this
value for invocations of the callback. For example, all iterative array methods and related ones like Set.prototype.forEach() accept an optional thisArg
parameter.
[1, 2, 3].forEach(logThis, { name: "obj" });
// { name: 'obj' }, { name: 'obj' }, { name: 'obj' }
Occasionally, a callback is called with a this
value other than undefined
. For example, the reviver
parameter of JSON.parse() and the replacer
parameter of JSON.stringify() are both called with this
set to the object that the property being parsed/serialized belongs to.
Arrow functions
In arrow functions, this
retains the value of the enclosing lexical context's this
. In other words, when evaluating an arrow function's body, the language does not create a new this
binding.
For example, in global code, this
is always globalThis
regardless of strictness, because of the global context binding:
const globalObject = this;
const foo = () => this;
console.log(foo() === globalObject); // true
Arrow functions create a closure over the this
value of its surrounding scope, which means arrow functions behave as if they are "auto-bound" — no matter how it's invoked, this
is bound to what it was when the function was created (in the example above, the global object). The same applies to arrow functions created inside other functions: their this
remains that of the enclosing lexical context. See example below.
Furthermore, when invoking arrow functions using call()
, bind()
, or apply()
, the thisArg
parameter is ignored. You can still pass other arguments using these methods, though.
const obj = { name: "obj" };
// Attempt to set this using call
console.log(foo.call(obj) === globalObject); // true
// Attempt to set this using bind
const boundFoo = foo.bind(obj);
console.log(boundFoo() === globalObject); // true
Constructors
When a function is used as a constructor (with the new keyword), its this
is bound to the new object being constructed, no matter which object the constructor function is accessed on. The value of this
becomes the value of the new
expression unless the constructor returns another non–primitive value.
function C() {
this.a = 37;
}
let o = new C();
console.log(o.a); // 37
function C2() {
this.a = 37;
return { a: 38 };
}
o = new C2();
console.log(o.a); // 38
In the second example (C2
), because an object was returned during construction, the new object that this
was bound to gets discarded. (This essentially makes the statement this.a = 37;
dead code. It's not exactly dead because it gets executed, but it can be eliminated with no outside effects.)
super
When a function is invoked in the super.method()
form, the this
inside the method
function is the same value as the this
value around the super.method()
call, and is generally not equal to the object that super
refers to. This is because super.method
is not an object member access like the ones above — it's a special syntax with different binding rules. For examples, see the super reference.
Class context
A class can be split into two contexts: static and instance. Constructors, methods, and instance field initializers (public or private) belong to the instance context. Static methods, static field initializers, and static initialization blocks belong to the static context. The this
value is different in each context.
Class constructors are always called with new
, so their behavior is the same as function constructors: the this
value is the new instance being created. Class methods behave like methods in object literals — the this
value is the object that the method was accessed on. If the method is not transferred to another object, this
is generally an instance of the class.
Static methods are not properties of this
. They are properties of the class itself. Therefore, they are generally accessed on the class, and this
is the value of the class (or a subclass). Static initialization blocks are also evaluated with this
set to the current class.
Field initializers are also evaluated in the context of the class. Instance fields are evaluated with this
set to the instance being constructed. Static fields are evaluated with this
set to the current class. This is why arrow functions in field initializers are bound to the instance for instance fields and to the class for static fields.
class C {
instanceField = this;
static staticField = this;
}
const c = new C();
console.log(c.instanceField === c); // true
console.log(C.staticField === C); // true
Derived class constructors
Unlike base class constructors, derived constructors have no initial this
binding. Calling super() creates a this
binding within the constructor and essentially has the effect of evaluating the following line of code, where Base
is the base class:
**Warning:**Referring to this
before calling super()
will throw an error.
Derived classes must not return before calling super()
, unless the constructor returns an object (so the this
value is overridden) or the class has no constructor at all.
class Base {}
class Good extends Base {}
class AlsoGood extends Base {
constructor() {
return { a: 5 };
}
}
class Bad extends Base {
constructor() {}
}
new Good();
new AlsoGood();
new Bad(); // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
Global context
In the global execution context (outside of any functions or classes; may be inside blocks or arrow functions defined in the global scope), the this
value depends on what execution context the script runs in. Like callbacks, the this
value is determined by the runtime environment (the caller).
At the top level of a script, this
refers to globalThis whether in strict mode or not. This is generally the same as the global object — for example, if the source is put inside an HTML