this
BaselineWidely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Thethis
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, wherethis
refers to the object that the method is attached to, thus allowing the same method to be reused on different objects.
The value ofthis
in JavaScript depends on how a function is invoked (runtimebinding), 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 theglobal object (in non-strict mode) orundefined
(instrict mode). TheFunction.prototype.bind()
method can create a function whosethis
binding doesn't change, and methodsFunction.prototype.apply()
andFunction.prototype.call()
can also set thethis
value for a particular call.
Arrow functions differ in their handling ofthis
: they inheritthis
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 ownthis
binding. Therefore, theirthis
value cannot be set bybind()
,apply()
orcall()
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
this
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 ofthis
depends on in which context it appears: function, class, or global.
Function context
Inside a function, the value ofthis
depends on how the function is called. Think aboutthis
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 ofthis
is the object that the function is accessed on. In other words, if the function call is in the formobj.f()
, thenthis
refers toobj
. 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 ofthis
is different. This is analogous to how function parameters work.
The value ofthis
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 theprototype chain.
const obj3 = { __proto__: obj1, name: "obj3",};console.log(obj3.getThis()); // { name: 'obj3' }
The value ofthis
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 prototypesNumber.prototype.getThisStrict = getThisStrict;console.log(typeof (1).getThisStrict()); // "number"
If the function is called without being accessed on anything,this
will beundefined
— but only if the function is in strict mode.
console.log(typeof getThisStrict()); // "undefined"
In non-strict mode, a special process calledthis
substitution ensures that the value ofthis
is always an object. This means:
- If a function is called with
this
set toundefined
ornull
,this
gets substituted withglobalThis
. - 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 prototypesNumber.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 ofthis
using theFunction.prototype.call()
,Function.prototype.apply()
, orReflect.apply()
methods. UsingFunction.prototype.bind()
, you can create a new function with a specific value ofthis
that doesn't change regardless of how the function is called. When using these methods, thethis
substitution rules above still apply if the function is non-strict.
Callbacks
When a function is passed as a callback, the value ofthis
depends on how the callback is called, which is determined by the implementor of the API. Callbacks aretypically called with athis
value ofundefined
(calling it directly without attaching it to any object), which means if the function is non–strict, the value ofthis
is the global object (globalThis
). This is the case foriterative array methods, thePromise()
constructor, etc.
function logThis() { "use strict"; console.log(this);}[1, 2, 3].forEach(logThis); // undefined, undefined, undefined
Some APIs allow you to set athis
value for invocations of the callback. For example, all iterative array methods and related ones likeSet.prototype.forEach()
accept an optionalthisArg
parameter.
[1, 2, 3].forEach(logThis, { name: "obj" });// { name: 'obj' }, { name: 'obj' }, { name: 'obj' }
Occasionally, a callback is called with athis
value other thanundefined
. For example, thereviver
parameter ofJSON.parse()
and thereplacer
parameter ofJSON.stringify()
are both called withthis
set to the object that the property being parsed/serialized belongs to.
Arrow functions
Inarrow functions,this
retains the value of the enclosing lexical context'sthis
. In other words, when evaluating an arrow function's body, the language does not create a newthis
binding.
For example, in global code,this
is alwaysglobalThis
regardless of strictness, because of theglobal context binding:
const globalObject = this;const foo = () => this;console.log(foo() === globalObject); // true
Arrow functions create aclosure over thethis
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: theirthis
remains that of the enclosing lexical context.See example below.
Furthermore, when invoking arrow functions usingcall()
,bind()
, orapply()
, thethisArg
parameter is ignored. You can still pass other arguments using these methods, though.
const obj = { name: "obj" };// Attempt to set this using callconsole.log(foo.call(obj) === globalObject); // true// Attempt to set this using bindconst boundFoo = foo.bind(obj);console.log(boundFoo() === globalObject); // true
Constructors
When a function is used as a constructor (with thenew
keyword), itsthis
is bound to the new object being constructed, no matter which object the constructor function is accessed on. The value ofthis
becomes the value of thenew
expression unless the constructor returns another non–primitive value.
function C() { this.a = 37;}let o = new C();console.log(o.a); // 37function 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 thatthis
was bound to gets discarded. (This essentially makes the statementthis.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 thesuper.method()
form, thethis
inside themethod
function is the same value as thethis
value around thesuper.method()
call, and is generally not equal to the object thatsuper
refers to. This is becausesuper.method
is not an object member access like the ones above — it's a special syntax with different binding rules. For examples, see thesuper
reference.
Class context
Aclass can be split into two contexts: static and instance.Constructors, methods, and instance field initializers (public orprivate) belong to the instance context.Static methods, static field initializers, andstatic initialization blocks belong to the static context. Thethis
value is different in each context.
Class constructors are always called withnew
, so their behavior is the same asfunction constructors: thethis
value is the new instance being created. Class methods behave like methods in object literals — thethis
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 ofthis
. They are properties of the class itself. Therefore, they are generally accessed on the class, andthis
is the value of the class (or a subclass). Static initialization blocks are also evaluated withthis
set to the current class.
Field initializers are also evaluated in the context of the class. Instance fields are evaluated withthis
set to the instance being constructed. Static fields are evaluated withthis
set to the current class. This is why arrow functions in field initializers arebound 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); // trueconsole.log(C.staticField === C); // true
Derived class constructors
Unlike base class constructors, derived constructors have no initialthis
binding. Callingsuper()
creates athis
binding within the constructor and essentially has the effect of evaluating the following line of code, whereBase
is the base class:
this = new Base();
Warning:Referring tothis
before callingsuper()
will throw an error.
Derived classes must not return before callingsuper()
, unless the constructor returns an object (so thethis
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 insideblocks orarrow functions defined in the global scope), thethis
value depends on what execution context the script runs in. Likecallbacks, thethis
value is determined by the runtime environment (the caller).
At the top level of a script,this
refers toglobalThis
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<script>
element and executed as a script,this === window
.
Note:globalThis
is generally the same concept as the global object (i.e., adding properties toglobalThis
makes them global variables) — this is the case for browsers and Node — but hosts are allowed to provide a different value forglobalThis
that's unrelated to the global object.
// In web browsers, the window object is also the global object:console.log(this === window); // truethis.b = "MDN";console.log(window.b); // "MDN"console.log(b); // "MDN"
If the source is loaded as amodule (for HTML, this means addingtype="module"
to the<script>
tag),this
is alwaysundefined
at the top level.
If the source is executed witheval()
,this
is the same as the enclosing context fordirect eval, orglobalThis
(as if it's run in a separate global script) for indirect eval.
function test() { // Direct eval console.log(eval("this") === this); // Indirect eval, non-strict console.log(eval?.("this") === globalThis); // Indirect eval, strict console.log(eval?.("'use strict'; this") === globalThis);}test.call({ name: "obj" }); // Logs 3 "true"
Note that some source code, while looking like the global scope, is actually wrapped in a function when executed. For example, Node.js CommonJS modules are wrapped in a function and executed with thethis
value set tomodule.exports
.Event handler attributes are executed withthis
set to the element they are attached to.
Object literals don't create athis
scope — only functions (methods) defined within the object do. Usingthis
in an object literal inherits the value from the surrounding scope.
const obj = { a: this,};console.log(obj.a === window); // true
Examples
this in function contexts
The value of thethis
parameter depends on how the function is called, not on how it's defined.
// An object can be passed as the first argument to 'call'// or 'apply' and 'this' will be bound to it.const obj = { a: "Custom" };// Variables declared with var become properties of 'globalThis'.var a = "Global";function whatsThis() { return this.a; // 'this' depends on how the function is called}whatsThis(); // 'Global'; the 'this' parameter defaults to 'globalThis' in non–strict modeobj.whatsThis = whatsThis;obj.whatsThis(); // 'Custom'; the 'this' parameter is bound to obj
Usingcall()
andapply()
, you can pass the value ofthis
as if it's an explicit parameter.
function add(c, d) { return this.a + this.b + c + d;}const o = { a: 1, b: 3 };// The first argument is bound to the implicit 'this' parameter; the remaining// arguments are bound to the named parameters.add.call(o, 5, 7); // 16// The first argument is bound to the implicit 'this' parameter; the second// argument is an array whose members are bound to the named parameters.add.apply(o, [10, 20]); // 34
this and object conversion
In non–strict mode, if a function is called with athis
value that's not an object, thethis
value is substituted with an object.null
andundefined
becomeglobalThis
. Primitives like7
or'foo'
are converted to an object using the related constructor, so the primitive number7
is converted to aNumber
wrapper class and the string'foo'
to aString
wrapper class.
function bar() { console.log(Object.prototype.toString.call(this));}bar.call(7); // [object Number]bar.call("foo"); // [object String]bar.call(undefined); // [object Window]
The bind() method
Callingf.bind(someObject)
creates a new function with the same body and scope asf
, but the value ofthis
is permanently bound to the first argument ofbind
, regardless of how the function is being called.
function f() { return this.a;}const g = f.bind({ a: "azerty" });console.log(g()); // azertyconst h = g.bind({ a: "yoo" }); // bind only works once!console.log(h()); // azertyconst o = { a: 37, f, g, h };console.log(o.a, o.f(), o.g(), o.h()); // 37 37 azerty azerty
this in arrow functions
Arrow functions create closures over thethis
value of the enclosing execution context. In the following example, we createobj
with a methodgetThisGetter
that returns a function that returns the value ofthis
. The returned function is created as an arrow function, so itsthis
is permanently bound to thethis
of its enclosing function. The value ofthis
insidegetThisGetter
can be set in the call, which in turn sets the return value of the returned function. We will assume thatgetThisGetter
is a non-strict function, which means it's contained in a non-strict script and not further nested in a class or strict function.
const obj = { getThisGetter() { const getter = () => this; return getter; },};
We can callgetThisGetter
as a method ofobj
, which bindsthis
toobj
inside its body. The returned function is assigned to a variablefn
. Now, when callingfn
, the value ofthis
returned is still the one set by the call togetThisGetter
, which isobj
. If the returned function was not an arrow function, such calls would cause thethis
value to beglobalThis
, becausegetThisGetter
is non-strict.
const fn = obj.getThisGetter();console.log(fn() === obj); // true
But be careful if you unbind the method ofobj
without calling it, becausegetThisGetter
is still a method that has a varyingthis
value. Callingfn2()()
in the following example returnsglobalThis
, because it follows thethis
fromfn2()
, which isglobalThis
since it's called without being attached to any object.
const fn2 = obj.getThisGetter;console.log(fn2()() === globalThis); // true in non-strict mode
This behavior is very useful when defining callbacks. Usually, each function expression creates its ownthis
binding, which shadows thethis
value of the upper scope. Now, you can define functions as arrow functions if you don't care about thethis
value, and only createthis
bindings where you do (e.g., in class methods). Seeexample withsetTimeout()
.
this with a getter or setter
this
in getters and setters is based on which object the property is accessed on, not which object the property is defined on. A function used as getter or setter has itsthis
bound to the object from which the property is being set or gotten.
function sum() { return this.a + this.b + this.c;}const o = { a: 1, b: 2, c: 3, get average() { return (this.a + this.b + this.c) / 3; },};Object.defineProperty(o, "sum", { get: sum, enumerable: true, configurable: true,});console.log(o.average, o.sum); // 2 6
this in DOM event handlers
When a function is used as an event handler, itsthis
parameter is bound to the DOM element on which the listener is placed (some browsers do not follow this convention for listeners added dynamically with methods other thanaddEventListener()
).
// When called as a listener, turns the related element bluefunction bluify(e) { // Always true console.log(this === e.currentTarget); // true when currentTarget and target are the same object console.log(this === e.target); this.style.backgroundColor = "#A5D9F3";}// Get a list of every element in the documentconst elements = document.getElementsByTagName("*");// Add bluify as a click listener so when the// element is clicked on, it turns bluefor (const element of elements) { element.addEventListener("click", bluify, false);}
this in inline event handlers
When the code is called from an inlineevent handler attribute, itsthis
is bound to the DOM element on which the listener is placed:
<button>Show this</button>
The above alert showsbutton
. Note, however, that only the outer scope has itsthis
bound this way:
<button> Show inner this</button>
In this case, thethis
parameter of the inner function is bound toglobalThis
(i.e., the default object in non–strict mode wherethis
isn't passed in the call).
Bound methods in classes
Just like with regular functions, the value ofthis
within methods depends on how they are called. Sometimes it is useful to override this behavior so thatthis
within classes always refers to the class instance. To achieve this, bind the class methods in the constructor:
class Car { constructor() { // Bind sayBye but not sayHi to show the difference this.sayBye = this.sayBye.bind(this); } sayHi() { console.log(`Hello from ${this.name}`); } sayBye() { console.log(`Bye from ${this.name}`); } get name() { return "Ferrari"; }}class Bird { get name() { return "Tweety"; }}const car = new Car();const bird = new Bird();// The value of 'this' in methods depends on their callercar.sayHi(); // Hello from Ferraribird.sayHi = car.sayHi;bird.sayHi(); // Hello from Tweety// For bound methods, 'this' doesn't depend on the callerbird.sayBye = car.sayBye;bird.sayBye(); // Bye from Ferrari
Note:Classes are always in strict mode. Calling methods with an undefinedthis
will throw an error if the method tries to access properties onthis
.
const carSayHi = car.sayHi;carSayHi(); // TypeError because the 'sayHi' method tries to access 'this.name', but 'this' is undefined in strict mode.
Note, however, that auto-bound methods suffer from the same problem asusing arrow functions for class properties: each instance of the class will have its own copy of the method, which increases memory usage. Only use it where absolutely necessary. You can also mimic the implementation ofIntl.NumberFormat.prototype.format()
: define the property as a getter that returns a bound function when accessed and saves it, so that the function is only created once and only created when necessary.
this in with statements
Althoughwith
statements are deprecated and not available in strict mode, they still serve as an exception to the normalthis
binding rules. If a function is called within awith
statement and that function is a property of the scope object, thethis
value is bound to the scope object, as if theobj1.
prefix exists.
const obj1 = { foo() { return this; },};with (obj1) { console.log(foo() === obj1); // true}
Specifications
Specification |
---|
ECMAScript® 2026 Language Specification # sec-this-keyword |