DEV Community

Cover image for Understanding: Context, Scope, Execution Context and 8 different This value in JavaScript explained by Paw Patrol!
Carlos Caballero
Carlos Caballero

Posted on • Originally published at carloscaballero.io

Understanding: Context, Scope, Execution Context and 8 different This value in JavaScript explained by Paw Patrol!

After more than 6 years explaining frontend to both vocational training and university students, I have found it difficult to understand the use of the reserved word “this” in JavaScript. The problematic of this reserved word has been hidden with the appearance of TypeScript and frameworks such as Angular, although under these layers there is still JavaScript, and the lack of knowledge causes errors that takes hours to fix.

Context Vs Scope

The first concepts we have to clarify is the difference between context and scope. These two terms are confused by many frontend developers (I myself took a while to understand them).

All the functions have associated scope and context. Scope defines the access to variables of a function when the function is invoked. On the other hand, Context is always the value of the reserved word this which is a reference to the object that owns the execution of the code.

Execution Context

JavaScript is a single-threaded language, so it can just execute one task at the same time. The rest of tasks are queued in the Execution Context. Unfortunately, when they say ‘execution context’, they mean scope (why did they do that?).

In each call, a function appends its context to the execution context. So each function creates its own execution context (its own scope).

Once the call ends, the context gets destroyed and the execution context will be transfered to the parent context. There is only one global context but finite function contexts.

“this” refers to global object

By default the execution context for an execution is global, which means that if a code is being executed as part of a simple function call then “this” refers to global object. In the case that you run your code in a browser the global object is “window” object while that in node.js the global object can be the special “global” or the “module.exports”.

The following code is running in a browser.

The following code is running in a node.js environment.

“this” refers to new instance

When a function is invoked with “new” keyword then the function is known as constructor function and returns a new instance. In such cases, the value of “this” refers to newly created instance.

The new keyword performs following four tasks:

  1. It creates new empty object e.g. obj = { };
  2. It sets new empty object’s invisible ‘prototype’ property to be the constructor function’s visible and accessible ‘prototype’ property. (Every function has visible ‘prototype’ property whereas every object includes invisible ‘prototype’ property)
  3. It binds properties or functions which are declared with this keyword to the new object.
  4. It returns a created object unless the constructor function returns a non-primitive value (custom JavaScript object). If constructor function does not include return statement then compiler will insert ‘return this;’ implicitly at the end of the function. If the constructor function returns a primitive value then return this; will not be inserted.

Now that we have a new execution context new properties can be defined for Dog function, in this case we got 2 new dogs of Paw Patrol, Turbot and Rubble.

As you may know, the great advantage of Javascript is using the prototype of each function (I recommend you to read about prototype pattern which is used in other languages object oriented, due to they are not native).

“this” refers to invoker object (parent object)

In JavaScript, the object’s properties can be a function or a simple value. When a object’s method is invoked then “this” refers to the object which contains the method which is being invoked.

In the following example you can see how the this value is different depends of the execution context.

“this” with call or apply methods

A function in JavaScript is also a special type of object. Every function has call, bind and apply methods. These methods can be used to set custom value of "this" to the execution context of function.

In the following code you can see how to change the execution context using the call method.

“this” with bind method

The bind method returns a new method with "this" refers to the first argument passed.

“this” with fat arrow function

As part of ES6, there is a new way introduced to define a function; using fat arrow (=>).

When a fat arrow is used then it doesn’t create a new value for “this”. “this” keeps on referring to the same object it is referring, outside the function. There is not a new execution context.

The following code the value of this is the function growUp which there is not a age attribute in its execution context.

The solution, in this case is not creates a new execution context. Therefore, we can use a fat-arrow.

“this” with fat arrow function and apply-call

When you use the apply or call methods over a fat-arrow function the this i not changed due to the fat-arrow does not own this. Therefore, the apply and call methods only call the original method with parameters while "thisArg" is ignored.

“this” with class sugar syntax

When we use class sugar syntax, it is common to use this the same way as any other object oriented programming language. However, the majority of OOP languages do not allow defining functions within functions.

Therefore, if we have a look at the following code, there is a method
displayName which includes a method called innerDisplay which uses the
keyword this. If we execute innerDisplay function in this context we will be creating a new execution context so this value will not belong to Dog class. Nevertheless, in order to solve this issue we can use any of the tricks explained along this blog. In this case, we will use apply function to change the context of innerDisplay function to Dog's context.

More, More, More…


*Originally published at https://www.carloscaballero.io on May 17, 2019.

Oldest comments (2)

Collapse
 
oleksandr profile image
Oleksandr • Edited

"It sets new empty object’s invisible ‘prototype’ property"
I guess it should be --proto-- ,I put dashes instead of underscores, instead here. And as for now we can access it and see it if console.log the object

Collapse
 
voidjuneau profile image
Juneau Lim

God, I didn't know that I could use this to refer to the global context. This is surprising.