“this” in JS exercise

📄 Table of contents

  • ‘this’ inside arrow functions
  • this’ in a function nested inside a method of an object
  • “this” inside classes

▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬ ✦ ✦ ✦ ▬▬▬▬▬▬▬▬▬▬▬▬▬▬

◉ “this” keyword in js

It has different values depending on where it is used:

  • In a method, this refers to the owner object.
  • Alone, this refers to the global object.
  • In a function, this refers to the global object.
  • In a function, in strict mode, this is undefined.
  • In an event, this refers to the element that received the event.
  • Methods like call(), and apply() can refer this to any object.

Note that I’m calling the walk method in this case, which is inside of the object.

But when we apply some slight changes, different results were obtained. Lets say, now we added another const named as newWalk which gives reference to the walk method in the user object. For simplicity, we can say newWalk is a function that calls the walk method in the user object.

This time we if we call the newWalk method by giving a reference to another method (walk) then most likely you will obtain undefined on the console. (Note that in my case we obtained a window object as I’m running this code in a React Project with Strict Mode disabled).

◉ bind-ing “this"

For example,

  • In the previous example where we aren’t able to access the user object using the this keyword, using the bind method you can solve all of that issues quickly.
  • We just have to pass .bind(an object that you want to give reference) to your function & we longer have to work with an undefined or window object, because the this keyword now always give reference the user object

◉ “this” exercises

var foo = {
name: "anil",
age: 30
};
function getDetails() {
return (this.name + " is + this.age + " yrs old.");
}
foo.logMyDetails = getDetails;
console.log(foo.logMyDetails());
//anil is 30 yrs old.
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
function Employee(name) {
this.name = name;
this.getName = function () {
return this.name;
}
}
var e1 = new Employee(“anil");
e1.getName();
#anil ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
function Employee(name) {
this.name = name;
}
Employee.getName = function () {
return this.name;
}
var e2 = new Employee("kumar");
e2.getName(); #TypeError
var e3 = e2.getName;
console.log(e3()); #TypeError
var e4 = e2.getName.bind(e2);
console.log(e4()); #TypeError
NOTE: if we re-write above getName as `Employee.prototype.getName` then above bind() will work and print "kumar" accordingly.▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬var x = "outermost";
var foo = {
x: "inner",
baz: {
x: "innermost",
bar: function () {
return this.x;
}
}
}
var go = foo.baz.bar; # "this" refers to global object
console.log(go());
console.log(foo.baz.bar())# outermost
# innermost

◉ ‘this’ inside arrow functions

The way ‘this’ works in arrow functions is different from generic functions. The arrow functions pick up the same context as that of the enclosing function. The ‘this’ keyword thus points to the context of the enclosing function. Consider the following example

The enclosing function for the arrow function ‘a’ is foo() and the context of the foo() function is the global object. Thus the ‘this’ keyword points out the global object here. Now consider the below example

The ‘this’ keyword of the function doo() points to the object ‘a’ since the enclosing function foo() is implicitly bounded to object ‘a’ and hence the doo() function picks up the context of foo().

Consider the below example for explicit binding and it should be pretty straightforward to guess the output.

Here too the ‘this’ of the doo function points to the object ‘a’ since the enclosing function foo is bound to object ‘a’ explicitly.

Exercises for the brave

Explanation

  • “outer func: this.foo = bar”
  • “outer func: self.foo = bar”

In line 7 we have an immediately invoked function expression (IIFE) and since this function is not bound to any object (implicitly or explicitly) ‘this’ will point to a global object hence this.foo is undefined as foo is not a vriable present on the global object. Thus the output for line 8 and line 9 is as follows

  • “inner func: this.foo = undefined”
  • “inner func: self.foo = bar”

Here self stores myObject as previously discussed and is accessible to IIFE because of closure in JS ( more about it here ). Thus self.foo is equal to “bar”.

Exercise 2:

Since arrow functions pick up the context of the enclosing function (func() here) ‘this’ and ‘self’ both point out to myObject and hence the output is as follows :

  • “outer func: this.foo = bar”
  • “outer func: self.foo = bar”
  • “inner func: this.foo = bar”
  • “inner func: self.foo = bar”

◉ What happens to ‘this’ in a function nested inside a method of an object?

Explanation: splitName() is a REGULAR function inside setName() but not directly bind to profile object. So, it sets “this” to `window` object, which doesn’t have a firstname property, , and hence the NaN outputs are obtained.

How do we solve this issue?

[1]. One solution is to assign the this value from the outer function to a variable to be used in the nested function like so:

var self = this;

[2]. Second solution to this problem involve using bind(), call() or apply().

[3]. Thirdly, converting it to fat arrow function, splitName=()=> function looses its “this” and gets value of this from enclosing body which is profile over here.

Explanation:

this.value refers to the value property in the ‘object’ object.

And add method has a parameter called val and number functions takes that as a parameter and return val * this.value, but this.value in the number functions is undefined and 10 * undefined is equal to NaN. So, the answer is 20 , NaN.

Output : 5,NaN, 5

◉ `this` inside Classes

Experience with Front-end Technologies and MERN / MEAN Stack. Working on all Major UI Frameworks like React, Angular.