What is "this" ?
Published: 2021-12-03 17:24:08

I will explain what is the meaning of "this" keyword in JavaScript on this post. There are a lot of rules that can determine the value of "this" om JavaScript. Here are the known 5 binding rules for "this" in JavaScript:

1. **Implicit Binding**
    
    Implicit Binding is applied when you invoke a function in an Object using the dot notation. Here is the example of implicit binding:
    
    ```js
    const user = {
      name: 'John',
      age: 20,
      run() {
        console.log(`${this.name} is running!`)
      },
      brother: {
        name: 'Doe',
        age: 21,
        run() {
          console.log(`${this.name} is running!`)
        }
      }
    }
    
    user.run() // output: John is running!
    user.brother.run() // output: Doe is running
    ```
    
2. **Explicit Binding**
    
    In this method, you can force a function to use a certain object as its **`this`**. Explicit Binding can be applied using call(), apply(), and bind(). Here is the example of explicit binding:
    
    ```js
    const user = {
      name: 'John',
      age: 20,
    }
    
    const foods = ['banana', 'papaya', 'melon'];
    
    function run(food1, food2, food3) {
      console.log(`${this.name} likes to eat ${food1}, ${food2}, and ${food3}`)
    }
    
    // This 3 example below will produce same output: John likes to eat banana, papaya, and melon
    // Example of call binding
    run.call(user, foods[0], foods[1], foods[2])
    
    // Example of apply binding
    run.apply(user, foods)
    
    // Example of bind binding
    const fnRun = run.bind(user, foods[0], foods[1], foods[2])
    fnRun()
    ```

3. **new Binding**
    
    New binding is applied when we create an object using Function Constructors. Here is the example of new binding:
    
    ```js
    function User(name, age) {
      this.name = name
      this.age = age
    
      this.run = function () {
        console.log(`${this.name} is running!`)
      }
    }
    
    const john = new User('john', 20)
    john.run() // output: John is running!
    ``` 

4. **Lexical Binding**
    
    Lexical binding is about ensuring that **`this`** is recognized because it is located in different function scope. Here is the example:
    
    ```js
    const user = {
      name: 'John',
      age: 20,
      foods: ['banana', 'papaya', 'melon'],
      run() {
        const greet = `Hello, my name is ${this.name} and I like to eat`
        const foods = this.foods.reduce(function (pFood, food, i) {
          if (i === this.foods.length - 1) {
            return `${pFood} and ${food}.`
          } else {
            return `${pFood} ${food},`
          }
        }, "")
    
        console.log(greet + foods)
      }
    }
    
    user.run()
    ```
    
    When you call run function there will be error: **`this.foods is undefined`**. This error happened because **`this`** inside the reduce function has different scope than **`this`** inside run function. You have to bind the this so the code will become like this:
    
    ```js
    const user = {
      name: 'John',
      age: 20,
      foods: ['banana', 'papaya', 'melon'],
      run() {
        const greet = `Hello, my name is ${this.name} and I like to eat`
        const foods = this.foods.reduce(function (pFood, food, i) {
          if (i === this.foods.length - 1) {
            return `${pFood} and ${food}.`
          } else {
            return `${pFood} ${food},`
          }
        }.bind(this), "")
    
        console.log(greet + foods)
      }
    }
    
    user.run()
    ```
    
    Now the output of this code should be like this: Hello, my name is John and I like to eat banana, papaya, and melon. This binding operation can be made simpler using arrow function that I will explain later in future posts.