Categories
JavaScript

JavaScript: Check ‘ this ‘ Out – Part I

I’ve struggled to understand the ‘this’ keyword for so long and have put off spending time to really understand it’s purpose. Whenever I tried to look into this, I would somewhat understand it, then somewhere along the way, I would become confused, which would lead to me taking a break…a really long break, and then eventually never getting back to it.

Every time I came across a situation where my code would break and found that it was ‘this’s’ (<- is that proper English? Lol ) fault, I would simply find a different solution so I didn’t have to use ‘this’. Avoiding the use of ‘this’ simply because I didn’t fully understand it is not really a great way to go about things.

“The ‘this’ keyword allows you to use functions in different contexts” – I’ve heard people say this a dozen times, and it just never made sense to me. It didn’t matter how many times I read and re-read an article; it just didn’t click. Then I realized that it was because I did not fully understand the word context

Now, some people say things like:

” It’s difficult to understand A without understanding B”.

To an extent, yes. However, I think this is improbable. Why? Because that statement assumes you understand how someone else’s brain works; you understand how they put pieces together, you understand how they got to a conclusion, and you literally know the in’s and out’s of their thought process. Really?

“I don’t see how you got to “B” without understanding “A”, so it impossible”.

See the problem with that statement? No? What is the first word in that sentence? “ I ”.  Just because they can’t see the connection doesn’t mean that you can’t.

I bring this up because my thought process is obviously unique to yours. I didn’t begin to understand ‘this’ until I understood context. Therefore I say this:

I think it’s fairly important to understand what context means before you understand this.

So when we say context, what do we mean?

Let us, first, take the actual definition from the internet:

“Context is the background, environment, setting, framework, or surroundings of events or occurrences. Simply, context means circumstances forming a background of an event, idea or statement, in such a way as to enable readers to understand the narrative or a literary piece.”

https://literarydevices.net/context/

Let us visualize the definitions above with a simple statement:

“You’re a fool”

There are not enough words to work off to determine the context for such a statement, so we will need to use some other means to determine the context. 

Here, let me help:

Based on the emoji on the left, it seems like they’re pretty upset, so the context behind “you’re a fool” is meant to be offensive.

Now the emoji on the right is laughing, so the context in “you’re a fool” can assume to be a friendly one.

This isn’t an article on the English language, so I think I’ll stop there.

Now, in javascript, when we’re using the this keyword,the context is referring to objects:

const myObject = { 
		property1: value1,
		property2: value2
}

This is the first step in understanding what ‘this’ is referring to; understanding that we’re referring to objects. We’ll come back to this later.

this

When using this, how and where you invoke a function is the context the this  is referring to when invoked.

There are a few ways for you to figure out how to determine what this is referring to in your code:

  • Implicit Binding
  • Explicit Binding
  • New Binding
  • Lexical Binding

Implicit Binding

Here is the definition of the word implicit from google:

“something that is suggested or implied but not ever clearly said”

Following up that definition up with an implicit binding example:

function addStuff (num1) {
	console.log( num1 + this.num2 );
};

Now, when you look at this function, what is num1? Num1 is the argument passed into the function when invoked. What about num2?

Side note for newcomers:

The word invoked means ‘calling’ the function.

// Here we're defining the function:
function myFunctionDefinition() { 
	//your code here
};

//Here, we're invoking ( calling ) the function above:
myFunctionDefinition() <- you invoke by appending parenthesis

Based on the use of this, it is suggesting that it is a number ( number 2 ), however, it doesn’t clearly state where the function is getting ‘num2’ from. It is impossible for you to know what num2 is without knowing where the function was called, and how the function was called; the context.

So if you were to look at the function above. You can ask the following question:

“In what context was the function invoked ( called )?”

Let us define an object with num2:

const objectOne = {
	num2: 100,
  	add: addStuff
};

Ok, so we defined an object with num2 and add as properties and gave them values of 100 and addStuff, respectively.

Let’ s combine all of the code above:

function addStuff (num1) {
	console.log( num1 + this.num2);
};

const objectOne = {
	num2: 100,
	add: addStuff
}

If I were to ask you what context ‘this’ is referring to, what would you say? You might say that it is referring to objectOne. Would you be wrong or right?

I’d say that you would be wrong, simply because there is not enough information.

Let’s add some more code:

function addStuff (num1) {
	console.log( num1 + this.num2);
};

const objectOne = {
	num2: 100,
	add: addStuff
}

const objectTwo = {
	num2: 500,
	num3: 300,
	add: addStuff
}

//invoked function
objectTwo.add(200) // expected output: 700

Per the above code, the function addStuff, was invoked using the objectTwo  object. Therefore the this keyword in the addStuff function is referencing the ‘num2’ property of the objectTwo object.

Let’s translate the original function to what the javascript engine does on the backend:

function addStuff(num1) {
	// this.num2 actually equals objectTwo.num2
	console.log(num1 + objectTwo.num2);
};

So essentially, when trying to figure out what this means, we can begin by using implicit binding; which says the following: “find where the function was invoked, then look to the left of the dot to determine the context of how the function was called”.

So lets look to the left of the dot in our invoked function:

objectTwo.addStuff(200)
//To the left of addStuff is objectTwo. 
//A pretty easy way to determine the reference of an implicitly defined 'this' keyword.

Explicit Binding

Here is the definition of the word explicit from google:

“Stated clearly and in detail, leaving no room for confusion or doubt.”

Following up that definition up with an explicit binding example:

function addStuff (num1) {
	console.log( num1 + this.num2);
};

const objectOne = {
	num2: 100
};

Ok so now we have a bit of a problem. We can’t implicitly invoke the addStuff function because objectOne does not have a method for the addStuff function. What will we need to do?

We can explicitly invoke the function using call.

Where does call come from?

By default all functions in javascript have a call property. Check it out for yourself. Open up web browser’s console and create the following function:

var f1 = function(x) {return x}

Next, type f1 in your console ( without parentheses )

Then click the drop down arrow for the second prototype, not the first one.

See! Every function has call property!

Here is a demonstration:

function addMoreStuff (num1, num2){
      console.log(num1 + num2 + this.num3)
}

const  objectFour = {
      num3: 300
};

// Explicitly invoking the addMoreStuff function with 'objectFour'

addMoreStuff.call(objectFour,100,200) // expected output: 600

So what does the above invoked function translate to in English?

” Hello JavaScript, please invoke (call) the addMoreStuff function with objectFour as the context. Oh, and since the function accepts two arguments, let’s pass in 100 and 200.”

I can see that this post is getting quite long, we will end it here and continue in part II with both the new and lexical bindings.