The rules of this
This
The this
keyword is a dynamic binding
that belongs to the environment record
of a function’s execution context
and whose main goal is dynamically accessing different objects in order to reuse code. More on that here:
The value this
refers to is some object (yes, an object; always; functions are objects, but it’s unlikely it refers to a function object
).
this
can be dynamic
since a new execution context
is created for a function each time it’s invoked.
It’s a dynamic binding
, but there are 4 rules that may help us understand what value this
points to. Let’s review them.
Oh, by the way, if you know Kyle Simpsons, yes, this is basically a rebranded explanation of his writings about the rules of this
. Go read his books if you want to go deep since they are light years away compared to this article.
4 rules of this
Default binding
function foo() {
console.log(this);
}
foo(); // the global object if not in strict mode, undefined in strict mode
Implicit binding: resolves to the context object
.
const obj = {
x: '',
foo() {
console.log(this);
}
}
obj.foo(); // { x: '', foo() { ... } }
Explicit binding
Soft binding: apply, call.
Hard binding: bind.
function foo() {
console.log(this);
}
const obj = {
x: '',
}
foo().call(obj); // obj
foo().apply(obj); // obj
const boundFoo = foo().bind(obj);
boundFoo(); // obj
new
binding
function Fn(x) {
console.log(this);
this.x = x;
console.log(this);
}
const myFn = new Fn(''); // logs {} first and { x: '' } second
``
Wait, how did that even happen!?
new
does 4 things:
Creates a
brand new object
under the hood.Makes sure the
brand new object
will be the value of thethis
keyword in thefunction environment record
of theexecution context
created when invoking the function being called withnew
(in the example,Fn
).Prototypally binds the
brand new object
's to the.prototype
of the function being called withnew
(in the example,Fn.prototype
).Invokes the function and returns the
brand new object
(unless the function returns some other object).
So in the example:
At the time
Fn
is called, thethis
keyword points to an object with no properties, but prototypally bound toFn.prototype
.this.x = x
adds anx
property to that object.The object is returned.
Rules of precedence
From more to less (more precedents override less precedents):
new
binding.Hard explicit binding (
bind
). *A custom version (not the one provided by JS) ofbind
could override thenew
binding, placing it as first., since JS'sbind
algorithm specifically takes thenew
keyword into account making sure it doesn't override it.Soft explicit binding (
call
,apply
).Implicit binding.
Default binding.
Quirks
Arrow functions behave differently. Arrow functions don't define local bindings for
this
. That means thefunction environment record
slot forthis
will be empty. The value of thethis
keyword in an arrow function will be resolved to the value ofthis
in itsfunction environment record
’s outerfunction environment record
, the one of theexecution context
where the arrow function was defined. So it will be resolved through the same mechanism as any user-authored binding.Beware: Some APIs, frameworks and libraries sometimes bind the
this
keyword. i.e., when the browser calls anevent handler
, it will bind thethis
keyword to the DOM node theevent handler
is attached to.