/ es5

What the heck is "this" Javascript keyword?

Whatever level of Javascript’s expertise you might have, “this” keyword has made everyone dizzy at some point or another. And if you are one of like me who came from an OOP background, it’s gonna suck and disappoint you. So, let’s clear the air and see what the heck is “this” javascript keyword.

Javascript isn’t OO, and so is “this”

Javascript is not object-oriented, even the latest version ES6 is also a lipstick on the pig. Javascript is a multi-paradigm language and inherits a lot of its traits from functional languages. That being said, a JS class in Javascript is actually a function underneath. Each function in Javascript is given a “this” value which defines the execution context/invocation context of that function.

Global Execution Context

Let’s say you have a global Javascript function, i.e. not part of an object, or a function, it’s execution context is the global execution context. So, if you are executing in a browser, that would be the window object.

console.log("Global: " + this); // Logs the window object. console.log(this === window); // true

Let’s try another example, look at the below snippet. We have a global function called “fnDemo”, which is not a part of any object or function. Hence, the function's “this” reference will resolve to the global execution context, viz. the window object.

const fnDemo = function() {
    return this;
}

console.log("Global this in a function" + fnDemo()); // window object.
console.log(fnDemo() === window); // true

Object’s Execution Context

On the other side, any method of an object invoked with the object reference will be going resolve this to the object the method is part of. Let’s see an example.

const objA = {
    name: 'Object A', 
    fnDemo: function() { 
        return this; 
    } 
} 
console.log("Object Reference: " + objA.fnDemo()); // Object A. console.log(objA.fnDemo() === objA); // true

Alright, so this is great, but remember as I said, it’s not OO and won’t refer to the owner but to the execution context. Let’s change the execution context/invocation context of the method above and try again.

const fnDemoClone = objA.fnDemo; 
console.log("Object Reference: " + fnDemoClone()); // global/window object
console.log(fnDemoClone() === window); // true

So, we used the same method but used the global context to execute it.

Closure

Let’s look at a more practical example of Javascript “this” implications and a pattern to get around this, viz. a closure. The following snippet uses an HTML element and invokes a method object using a global execution context.

const objB = { 
    fnDemo: function() { 
        alert(this); 
    }, 
 } 
 const fnBtnDemoRef = objB.fnDemo;
 <button id="button1" onclick="fnBtnDemoRef()">Click Me Btn1</button>

What would you expect the output. Well the global window object, because the invocation was done over global context. But, what if you want to pass the HTML button invocation context to it, there is a pattern to do that, called Closures.

const fnBtnDemo1Ref = function(that) { 
    (function() { 
        alert(that); 
    })(); 
}; 
<button id="button2" onclick="fnBtnDemo1Ref(this)">Click Me Btn2</button>

The output - HTML element, since we are passing the value of this from the button and letting the function closing over that value. Hence, the closures. The closure is a deep topic, and we will write more about this.

Since this is a common use case, and closures are not easy to understand. Modern browsers offer a nice way to work that out without closures. In the below snippet, we are going to define onclick handler by passing in a reference to the function.

//Button 3 Example of onclick event handler. <button id="button3">Click Me Btn3</button> document.getElementById("button3").onclick = fnBtnDemoRef;

The result, same as the snippet above. The function is invoked not withthe global execution context, but with the execution context of the HTML element.

Constructing an object

We typically also use the “new” keyword on a function to create a new object. If that is the case, the “this” reference will point to the newly created object.

// As a constructor example. 
const fnConstExample = function() { 
    this.name = "The Const Example"; 
}
const objConst = new fnConstExample();
console.log(objConst.name); // The Const Example

Strict Mode

Strict Mode is a restricted environment of Javascript to avoid inconsistencies and errors. Note that in the strict mode, the global context is not mapped to the function invocation. Since there was no explicit intentional execution context, strict mode sets it to undefined. Look at the below examples.

// Non Strict mode check 
function fnNonStrictMode() { 
    const fnDemo = function() { 
        alert(this); 
    }; 
    return fnDemo(); 
} // Strict mode check 
function fnStrictMode() { 
    'use strict'; 
    const fnDemo = function() { 
        alert(this); 
    }; 
    return fnDemo(); 
} 
<button id="button4" onclick="fnStrictMode()">Click Me Btn4 Non-Strict</button>
<button id="button5" onclick="fnNonStrictMode()">Click Me Btn4 Strict</button>

In the above snippet, the button 4 works fine as expected before, showing the global object, but the button 5 which is using the strict mode will display undefined.

Examples

I recommend you to look at the above examples here and execute it. Here’s a gist of the above examples.

Here are the results of executing the above in the browser console.

Example result snippet of this execution context

In the other article here, I have explained how “bind” method can be used to manipulate the “this” reference in some of the common usage patterns in Javascript.

“All the example’s above are in the below code pen. Codepen is using JQuery syntax for adding content to the div’s.

Love Hasija

Love Hasija

Full Stack Research Engineer, Software Architect | Helped build next generation software systems | Distributed Systems Fanatic | Open Source Hacker.

Read More
What the heck is "this" Javascript keyword?
Share this