In this article, I want to give you a new approach to learning the infamous JavaScript "this".
this
is a runtime binding
this
is not an author-time binding, but a runtime binding. This means this
has nothing to do with where a function is declared, but how/where the function is called.
When a function gets called, the engine creates an execution context. Within the execution context, one of the properties is the this
reference, which will be used for that function's execution.
Rules, rules, rules
-
Default binding
Default binding is the most basic rule, which happens for standalone function invocations. It points
this
to the global object.In
strict
mode, the default binding is set toundefined
because the global object is not eligible here-
Example
function foo() { console.log(this.a); } var a = 2; foo(); // 2
-
-
Implicit binding
Implicit binding happens when a function is called within an
Object
, which pointsthis
to the function "containing" object.-
Example
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo(); // 2
Although the function is declared outside and only referenced in the object, it's still considered that the object "contained" the function.
-
-
Implicitly lost
Implicit binding only happens when the function is called using a reference within an object, such as
obj.foo()
. When an implicitly bound function loses its binding, it will also lose its implicit boundthis
.-
Example
function foo() { console.log(this.a); } var obj = { a: 2, foo: foo } var bar = obj.foo; // lost implicit bound var a = "global" bar(); // global
Implicitly lost often happens when we are making explicit or implicit references. The above code is an example of implicitly lost due to explicit reference. Implicit references happens a lot when we are dealing with passing functions as parameters
-
Example
function foo() { console.log( this.a ); } function doFoo(fn) { // implicit reference, `fn` is just another reference to `foo` fn(); // <-- call-site! } var obj = { a: 2, foo: foo }; var a = "oops, global"; // `a` also property on global object doFoo( obj.foo ); // "oops, global"
-
-
Explicit binding
We can force a function's
this
binding by using itscall(...)
,apply(...)
method. All of these methods take a context object as thethis
for the function invocation.-
Example
function foo() { console.log( this.a ); } var obj = { a:2 }; foo.call( obj ); // 2
-
-
Hard binding
We can force a function's binding forever using its
bind(...)
method. -
API call "context"
Many of the built-in function provide an optional parameter for you to set
this
reference. -
**new
binding**Whenever we use the
new
keyword to create a constructed object, the newly created object is set as thethis
reference for that function call.-
Example
function foo(a) { this.a = a; } var bar = new foo(2); console.log( bar.a ); // 2
-
-
Arrow function binding
Arrow functions automatically points its
this
at the enclosing scope, and it can not be overwritten.
In this
order
Here we ranked the rules from the highest priority to the lowest.
- Called with
new
, use the newly constructed object - Called with
call
orapply
? Use the specified object - Called within a context object? Use it
- Default:
undefined
instrict
mode, otherwise global object