DEV Community

Zen Oh
Zen Oh

Posted on

What is "this" ?

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:

    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:

    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:

    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:

    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:

    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.

Discussion (0)