JavaScript - this Keyword

Hello there, aspiring JavaScript developers! Today, we're going to embark on an exciting journey into the world of the this keyword. As your friendly neighborhood computer science teacher, I'm here to guide you through this sometimes tricky, but always fascinating, concept. So, grab your favorite beverage, get comfortable, and let's dive in!

JavaScript - this Keyword

What is 'this' keyword?

Imagine you're at a party, and someone shouts, "Hey, you!" Who would turn around? Everyone, right? But if they said, "Hey, Sarah!" only Sarah would respond. In JavaScript, the this keyword is like saying "Hey, you!" to an object. It's a way to refer to the current object in context.

The this keyword is a special identifier that's automatically defined in the scope of every function. But here's the catch - its value is determined by how a function is called. This dynamic nature of this is what makes it both powerful and sometimes confusing.

Which object does the 'this' refer to?

Now, this is where things get interesting. The object that this refers to can change depending on how and where it's used. It's like a chameleon, changing its colors based on its surroundings. Let's look at some scenarios:

Syntax

Before we dive deeper, let's quickly look at how we use this:

console.log(this);

Simple, right? But don't let its simplicity fool you. The magic (or mischief) happens when we use it in different contexts.

JavaScript 'this' in the Global Scope

When used in the global scope (outside of any function), this refers to the global object. In a browser, that's usually the window object.

console.log(this === window); // true

this.myGlobalVar = "I'm global!";
console.log(window.myGlobalVar); // "I'm global!"

Here, this is like the VIP pass that gives you access to the entire party (global scope).

JavaScript 'this' in a Function

When this is used inside a regular function, its value depends on how the function is called.

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

showThis(); // window (in non-strict mode)

In this case, this is like a lost puppy, attaching itself to whatever is around - which in non-strict mode is the global object.

'this' in a Function in Strict Mode

Strict mode is like the strict teacher who doesn't let you get away with anything. In strict mode, this inside a function is undefined unless set explicitly.

"use strict";
function strictThis() {
    console.log(this);
}

strictThis(); // undefined

'this' in a Constructor Function

When a function is used as a constructor (with the new keyword), this refers to the newly created object.

function Person(name) {
    this.name = name;
    this.greet = function() {
        console.log("Hello, I'm " + this.name);
    };
}

const john = new Person("John");
john.greet(); // "Hello, I'm John"

Here, this is like a birth certificate, establishing the identity of the newly born object.

'this' in an Arrow Function

Arrow functions are the rebels of the JavaScript world. They don't bind their own this but inherit it from the enclosing scope.

const obj = {
    name: "Alice",
    sayHello: () => {
        console.log("Hello, " + this.name);
    }
};

obj.sayHello(); // "Hello, undefined"

In this case, this in the arrow function doesn't refer to obj, but to the surrounding scope (likely the global scope).

'this' in the Object Method

When this is used in a method (a function that's a property of an object), it refers to the object the method was called on.

const car = {
    brand: "Toyota",
    getBrand: function() {
        return this.brand;
    }
};

console.log(car.getBrand()); // "Toyota"

Here, this is like a loyal butler, always referring to its master (the object).

'this' in a Child Function of an Object Method

This is where things can get tricky. In a function within a method, this doesn't refer to the object anymore.

const restaurant = {
    name: "Tasty Treats",
    getMenu: function() {
        function displayName() {
            console.log(this.name);
        }
        displayName();
    }
};

restaurant.getMenu(); // undefined

In this case, this in displayName() refers to the global object, not restaurant.

JavaScript 'this' in Event Handlers

In event handlers, this typically refers to the element that received the event.

<button id="myButton">Click me!</button>

<script>
document.getElementById("myButton").addEventListener("click", function() {
    console.log(this); // <button id="myButton">Click me!</button>
});
</script>

Here, this is like a spotlight, focusing on the star of the show - the element that was clicked.

Explicit Function Binding in JavaScript

Sometimes, we want to be the boss and tell this exactly what it should be. We can do this using call(), apply(), or bind().

const person1 = { name: "Alice" };
const person2 = { name: "Bob" };

function sayHello() {
    console.log("Hello, " + this.name);
}

sayHello.call(person1); // "Hello, Alice"
sayHello.apply(person2); // "Hello, Bob"

const boundHello = sayHello.bind(person1);
boundHello(); // "Hello, Alice"

These methods are like a director, telling this exactly which role to play.

JavaScript 'this' Precedence

Now, let's summarize the precedence of this binding:

Rule Precedence
new keyword 1 (Highest)
Explicit binding (call, apply, bind) 2
Method invocation 3
Function invocation 4 (Lowest)

Remember, arrow functions are special and always inherit this from their surrounding scope.

And there you have it, folks! We've journeyed through the land of this, exploring its many faces and quirks. Remember, understanding this is like learning to ride a bike - it might be wobbly at first, but with practice, you'll be zooming around in no time. Keep coding, keep exploring, and most importantly, keep having fun with JavaScript!

Credits: Image by storyset