The direction of this in class

When learning react recently, because react uses class to build components, it's a bit confused about the direction of this in class. Now make a summary.

Binding priority of this

There are four ways to bind this, and the priority decreases step by step.
The essence of this is: this has nothing to do with scope, only with execution context.

1. Call the instance created by new. this points to the current instance.

eg.

// Binding on instance
let cat = new Cat()
cat.speak()

2. Display binding

Use call, apply, or bind

function jump() {
  console.log(this.name)
}
const obj = {
  name: 'Rice grain',
  jump
}

jump = jump.bind(obj)

jump() // Rice grain

3. Method binding in objects

function jump() {
  console.log(this.name)
}
let obj = {
  name: 'Rice grain',
  jump
}

obj.jump() // Rice grain

4. Default binding

In strict mode, this is undefined, otherwise it is a global object.

Binding of attribute and method in Class

class Cat {
    constructor(name, age) {
        // name binding age unbound
        this.name = name
    }
    jump() {
        console.log('jump',this)
    }
    // Static methods that can be called directly are often used to create utility functions for an application.
    static go() { 
        console.log(this)
    }
}
// It can be called directly, just like using static.
Cat.drink = function() {
    console.log('drink',this)
}

Cat.prototype.eat = function() {
    console.log('eat',this)
}
// Use arrow function binding
Cat.prototype.walk = () => {
    console.log('walk',this)
}

let cat = new Cat('cat Rice in China', '5 Months')

Print out prototype objects of cat and cat

As you can see, the method of the instance created by Cat is mounted on the proto object of the instance. Because Cat. Proto and Cat.prototype point to the same object, when you mount or overwrite the original method on Cat. Proto, all instances created by Cat will share the method, and all instances are searching for methods on the original object through the prototype chain generated by the proto attribute.

But static methods are not shared with the instance because they are not mounted on the prototype object.

Properties are attached to instances, that is, each created instance has its own properties with different values.

Binding of this in class

Foreground Abstract: when we print typeof Cat, we can see that it is a function type. The class class in ES6 is actually just a syntax sugar, which can be implemented with ES5. The instance cat created by the constructor cat is an object. When initializing the cat instance, the property on this will be attached to the instance object in the constructor.

Also keep in mind that the direction of this is scope independent and context sensitive when calling to execute a function.
Example 1:

class Cat {
    constructor(name, age) {
        this.name = name
    }
    run() {
        console.log('run',this)
    }
}
let cat = new Cat('Rice grain', '5 Months')
cat.name // 'rice grain'
cat.run() // run Cat {name: "rice grains"}

When cat.run() is called, the current context is cat, so its this refers to the instance of cat.
Example two:

class Cat {
    constructor(name, age) {
        this.name = name
        this.jump = this.jump.bind(this)
        this.drink = () => {
            console.log('drink',this)
        }
    }
    run() {
        console.log('run',this)
    }
    jump() {
      console.log('jump',this)
    }
    static go() { 
        console.log('go',this)
    }     
}

Cat.prototype.walk = () => {
    console.log('walk',this)
}

let cat = new Cat('Rice grain', '5 Months')
let run = cat.run
let jump = cat.jump
let go = Cat.go
let walk = cat.walk
let drink = cat.drink


run() // run undefined
jump()  // jump Cat {name: "rice grain", jump: Ji}
Cat.go() // go class Cat {}
go() // go undefined
cat.walk() // walk Window
walk() // walk Window
cat.drink() // Drive cat {Name: "rice grain", jump: ƒ, drive: ƒ}
drink() // Drive cat {Name: "rice grain", jump: ƒ, drive: ƒ}

First look at the run method: when the method in the instance is assigned to a variable, but only the method reference is given, so when the variable executes the method, it actually changes the execution context of the method. The original execution context is instance cat, and it will be executed after the assignment. The context becomes global, and this is bound by default. The strict mode is used in class. In this mode, the global this is bound to defined by default, not in strict mode. If it is executed in the browser, this is bound to window by default.

Jump method: because when the constructor executes, the context of jump execution - Cat instance is explicitly bound. According to the priority of this binding at the beginning of this article, explicit binding > default binding. So the execution context of jump is still cat instance.

Go method: go method is defined by static method. It cannot share instance cat. It can only be called directly on the constructor cat.

walk and drive methods: these two methods are defined with arrow functions. This of arrow function is bound when defining function, not during execution. In short, when a function is defined, this inherits the object that defines the function.

So walk is defined in Cat.prototype.walk, and this point is window. No matter which variable is assigned later, it is only a reference of the function, so this or window.

Similarly, when the driver is defined, this refers to the constructor.

Keywords: Javascript React Attribute

Added by ziong on Tue, 29 Oct 2019 13:19:46 +0200