DEV Community

loading...

The Common Enemy, JavaScript's "This" Keyword Saves The Day

ogwurujohnson profile image Johnson Ogwuru ・4 min read

Developers everywhere both seasoned and those just beginning to code, all at one time or still never understand the this keyword of javascript, most view it as being complex. The key to understanding and simplifying the ideas behind the this keyword in JavaScript is by understanding;

  1. Why we need this and why we should use this in the first place.
  2. How this works.
  3. How to identify what this is bound to.

According to Getify in his "you dont know Js series", explains this as a "special identifier keyword that's automatically defined in a scope of every function,but what exactly it refers to bedevils even seasoned JS Developers".

But why do we need to this?

Getify explains that this provides a more elegant way of implicitly "passing along" an object reference, leading to cleaner API design and easier re-use. The more complex your usage pattern is, the more clearly you will see that passing context around wouldn't be an advantage to you, nor anyone reading your code. This allows us to reuse functions with different context, in other words it allows us to decide which object should be focal when invoking a functional method.

There are lots of confusions associated with the use of this;
Most developers try to think about it too literal. Most developers feel this refers to the function itself, but the fail to note that this binding has nothing to do with where a function is declared, but has instead everything to do with the manner in which the function is called.

But how do we identify what `this is bound to?;
Note:

  1. The value of this is usually determined by a functions execution context. Execution context here means how the function is called.
  2. It is important to know that this may be different (refer to something different) each time the function is called.

Brandon Morelli in his article "Javascript: The keyword 'this' for beginners", outlined that there are five general rules that you can use to determine what this is bound to;

A. Global Object:Fire up your chrome console(ctrl+shift+j), type ; console.log(this), you notice what is outputted is the window object, this means that 'this' refers to the global object and it is as such because we are in the global scope. But to further prove that this here refers to the global object, lets declare a variable, in your console paste this code, var myName =
Johnson;
, now when you call myName it returns Johnson but guess what else would return Johnson now copy and paste the code window.myName and see what it returns.

What all of this mean is that every variable declared in the global scope is attached to the global or window object and that was why this when declared in the global scope refers to the global object.

Remember our Note (1); the value of this is determined by when it is called. Say we have a function that returns this what do you think the console would log; try guessing before you run the code. The result is that the this, this time would refer to the window object and why is that? Because the nearest parent object to the this keyword is still the global object.

function name()
{
    console.log(this);
}

name();

Another rule we could use to determine what this is bound to is the;

B. Declared Object:
In this case when the keyword this is used inside of a declared object say var person = {};, the this keyword refers to the nearest parent object the method is called on. Take an example;

var author = 
{
  first: 'Johnson',
  last: 'Ogwuru',  
  full: function() 
    {
      console.log(this.first + ' ' + this.last);
    }
};

author.full();

It logs=>(Johnson Ogwuru). To further prove that this in this context refers to the nearest parent object; copy and run the following code on your console;

var author = 
{
  first: 'Johnson',
  last: 'Ogwuru',  
  full: function() 
    {
      console.log(this);
    }
};
author.full();

As you would see the console returns the person object, proving this has taken the value of author. One last thing, remember we said that this refers to the nearest parent object; but how about a situation where we have nested statements;

var author = 
{
  first: 'Johnson',
  last: 'Ogwuru',  
  full: function() 
    {
      console.log(this.first + ' ' + this.last);
    },
  author2: 
    {
        first : "Jane",
        last: "Johnson",
        full: function() 
        {
          console.log(this.first + ' ' + this.last);
        }
    }
};

author.full();
author.author2.full();

When author.full() is invoked, inside the function this is bound to the author object, and when author.author2.full() was invoked, this was bound to the author2 object which is the nearest object to it.

Final Points to Note:

  1. The value of this is usually determined by a functions execution context.
  2. In the global scope, this refers to the global object.
  3. According to getify, we use they this keyword to avoid complexities. Imagine a scenario in our previous example where we tried using author.first instead of this.first and it happens we have another global variable(that we might or might not be aware of) with the name author, this trying to reference it, would lead to difficult-to-debug errors.

To read more on this follow this links;

  1. codeburst
  2. JavaScriptisSexy

Discussion

pic
Editor guide
Collapse
jishvi profile image
Jishnu Vasanth

I think, by using lexical scoping, arrow function solves the confusion around this to an extent.

Collapse
ogwurujohnson profile image
Johnson Ogwuru Author

Yurp, ure right. Thanks alot for the additional information

Collapse
jochemstoel profile image
Jochem Stoel

@jishvi Can you elaborate?

Collapse
jishvi profile image
Jishnu Vasanth

Arrow function does not create its own this context. Instead, it binds this keyword lexically which is a fancy way of saying that it takes the meaning of this from the enclosing context. In ES5 we can either use Function.prototype.bind to grab the this value from another scope to change a function’s execution context or assign the value of this to another variable (var that = this).

 var Person = function(name) {
    this.name = name;
    this.sayNameAfterTwoSeconds = function() {
        setTimeout(() => {
            alert(this.name)
        }, 2000);
    };
};

In this code caller of setTimeout is window object. But inside setTimeout, this refers to its current surrounding scope and no further. Thus the inner function knew to bind to the inner function only, and not to the object’s method or the object itself.

Thread Thread
jochemstoel profile image
Jochem Stoel
Arrow function does not create its own this context. Instead, it binds this keyword lexically which is a fancy way of saying that it takes the meaning of this from the enclosing context.

That is precisely what I said.

Collapse
jochemstoel profile image
Jochem Stoel

I hate to sound like an asshole but someone who does not understand this not just in JavaScript but any object oriented language is not a developer.

Collapse
ben profile image
Ben Halpern

I don't think that's true at all. People are universally confused about the this keyword in JS.

My all-time most popular tweet is demonstration that this is a shared problem.

Collapse
jochemstoel profile image
Jochem Stoel

Sorry but I don't see it that way. A developer knows what he/she is doing. If you write code without understanding basic fundamentals like context and this you are not really a developer but a hobbyist maybe or a person with an interest in development.
This is something you should have mastered during the first semester of your education even if you are one of those 'self educated' developers like myself.
Do you think an employer will hire a developer who doesn't know this stuff? The stupidity!

The fact that this tweet got so much response is because you made a clever/funny word joke. (I think it is funny too) It doesn't mean everybody who liked, retweeted or ponied it agrees with the topic of this discussion.

Maybe I am wrong. I guess sadly statistically some employer out there will hire you regardless but these will be small businesses with their very own WordPress website or something and not organizations focused on development.

Anywho, if you don't understand this then you are incompetent. Absolutely no offense to the author of this article, who is probably a young developer and did a good job at explaining.

Thread Thread
theodesp profile image
Theofanis Despoudis

It not always true. There are situations where even the most competent ones struggle, usually when the problem analytical in nature, for example, try to determine the value of z just by reading the following code snippet ( no cheating):

let x = 2;

let y = {
    a: () => this.x = 5,
    b: function () {
        this.x = '11';
    }
}

y.a();
y.b();

var z = x + parseInt(y.x, x) + window.x;

The real question is whether if you fall for it, would you be considered incompetent? Probably not

Thread Thread
jochemstoel profile image
Jochem Stoel

Ha! I might actually be incompetent after all. I was not aware of the parseInt optional radix parameter.

As for the context stuff (your code example) honestly this is all so obvious and straightforward. A no-brainer I believe is the expression. Arrow functions don't bind their own this so when you reference this from an arrow function it refers to the parent/originating context. Knowing that, what is the confusion all about?

I don't have to examine it carefully or think deeply about which values change where in what context and why. I have internalized this and it has become trivial and automatic.

Also, this became a bad example when you added window.x at the end. window is not declared anywhere in the snippet. If you are gonna have a debate about context then don't assume a very context specific global object. (it would have been better to put this.x in stead of window.x)
I am not intentionally being a smart-ass pointing this out. You have to understand that a lot of JavaScript does not run in a browser and has no window. For starters this is the case for pretty much all Node modules. Workers don't have a window object either. Javascript as a language doesn't even have a console object but yeah I know that is not the point. I have used many different JavaScript interpreters and written a lot of 'context-free' code so I might be a little obsessive.
Speaking of context specific. Did you know that V8 by itself has no Events? The Event class is written entirely in JavaScript and is not part of the ECMAScript language.

It is important to understand that V8 is only the interpreter. A lot of standard and very common objects/apis that you know do not exist yet. This includes the console object like we have discussed in this article but also the Event class and its children.
More: V8Ception

Oh well. Discussing this I did come to realize that you guys are probably right. Having difficulty understanding scopes and context is probably a lot more normal/common than I thought and I just happen to stand out tremendously in this particular area with my amazing abilities and understanding.

Thread Thread
theodesp profile image
Theofanis Despoudis

OK, so what is the value of z then and why? Assume the window is the global object.

The whole question was intentional as its more than the window or the this in an arrow function. Its the combination of all those things plus putting your self in a real working environment with issues to fix and deadlines to hit etc that makes them really tricky.

And yes I'm aware of Node and V8 and the event class (I've written server-side Javascript before)

Collapse
gmartigny profile image
Guillaume Martigny

Just remember that being a developer mean nothing more than "can open an editor". But, I get your point.
I think what you're trying to say is :

It's essential to understand the this keyword in a object oriented environment. this is an important part of the abstraction of common code into class.