Blog

Front End Development topics with a touch of humor

More on this

This round two

October 2, 2020


In an earlier post, I examined a few tidbits about this, the confusingly named and implemented JavaScript language feautre. I defined it as the reference to an object that depended on the execution context.

Location, it turns out, is very important. Especially when we are dealing with object methods. More on that later.

This,we find, is the window for things like global variables or for functions. But in strict mode, this is undefined inside a function. But it is the Window outside the function.

However, this can be changed--defined explicitly--by using call() or apply() and passing in a custom object. Then the this will be set to that object.

And this is only the beginning of the weird and contradictory rules pertaining to this. I again have sympathy for non-native English speakers, for learning the vagaries of through and thorough and throw must be similar to the current issue.

More on the ways of this

No, this makes perfect sense, honest!

In fact, there are many more weirdnesses to come, but I have no intention on writing a You Don't Know JS book. It makes more sense to me to just go over the common situations I myself have used. I see no purpose in reproducing strange situations and edge cases I've never even seen in the wild.

Object method

Here is one of them. We've seen that the this inside a function is Window.

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

            //Window 
        

Except in strict mode:

            function whatIsThis() {
                'use strict';
                console.log(this);
            }

            //undefined
        

But what if the function is a method of an object?

            const myObj = {
                myFunc : function() { 
                            console.log(this);
                        }
            }

            myObj.myFunc();
            //myFunc
        

Ah-ha-ha! (French accent) This has changed! Now this is myFunc. When called as a method to an object, this is set to the object the method is called on. In this case, the method is called on itself, so myFunc is this.

            const myObj = {
                who: "Naturally",
                myFunc: function() {
                            console.log(this.who)
                            }
                }
            myObj.myFunc();
            //"Naturally"
        

According to the rule that for the method of an object, the this is set to the object the method is called on, in this case, the object is myObj. Inside the function, this is bound to myObj.

But this isn't because of where myFunc was defined, or that it was defined inside myObj. It is simply the behavior of object methods in general. Observe:

            const myObj = {
                who: "Who"
            }

            function myFunc() {             //an independent function
                console.log(this.who);
            }
            
            myObj.func = myFunc;            //the function is assigned to an object key

            myObj.func();                   //call the function as a method of myObj
            //"Who" 
        

The function was defined outside the object. It was then assigned to the object and called from that context. The this changed from the global context to myObj, which allows it to then access who, a property of the object.

In a nested situation, the this refers only to the local context. For example, consider an object nested inside an object. Does the this refer to the outside object or the inside object?

            const myObj = {
                innerObj : {
                    who: "Who"
                },
                who: "Naturally"
            }
        

Here I've set up a nested object--innerObj inside of myObj. Notice they both have a duplicate property--who.

            function myFunc() {             //an independent function
                console.log(this.who);
            }
            myObj.innerObj.testFunc = myFunc;  //assign the function to innerObj
            myObj.innerObj.testFunc();         //this is the innerObj
            //"Who"

            myObj.testFunc = myFunc;            //assign the function to myObj (the outer object)
            myObj.testFunc();                   //this is myObj
            //"Naturally"
        

Do you follow? In the nested object, when I assigned the function to the nested object and called it, the this was the inner object, ignoring the outer object. When I assigned the function to the outer object, then the this changed to the outer object.

This is a strange and interesting behavior. But wait! There's more!

Let's set up two objects that aren't nested, and assign a method to the first one.

            const myObj = {
                who: "Who",
                myFunc: function() {
                    console.log(this.who)
                }
            }

            const hisObj = {
                who: "Naturally"
            }
        

When we call myFunc, the this is myObj, where it was called.

            const myObj = {
                who: "Who",
                myFunc: function() {
                    console.log(this.who)
                }
            }
            myObj.myFunc();
            //"Who"
        

Note that the this is myObj because the method was called from there, not because myFunc is a method of myObj. Observe:

            hisObj.test = myObj.myFunc;      //test is a new key with the function assigned to it
            hisObj.test();                   //the this changed
            //"Naturally"
        

What is this sorcery? I created a key called test that has a reference to myObj's method, myFunc. When I call test(), it executes the method from within hisObj, thus the who is "Naturally." This reveals that the this has changed to hisObj.

For method calls, this depends on location.