JS function call this pointing problem in detail

This in the function call

Before we can discuss the “this” pointing problem in function calls, we first need to know why the problem exists, or in other words, where the “this” pops up during a function call.

The truth is that when a function is called, it takes two arguments, this and arguments, in addition to the formal arguments that are specified during the declaration, so the way the function is called causes this to refer to differently.

In JS function invocation mode has 4 kinds: method invocation mode, function invocation mode, constructor invocation mode, apply invocation mode.

The following are explained in turn.

Method invocation pattern

When a function is a property of an object, the function is called a method.

If this method is called (in the form of.method name ()) and this is used in the method, this is bound to the object. Look at the following example:

    let myObject = {
      value: 0.increment: function(inc){
        // When the increment method is called, this refers to myObject
        this.value += typeof inc === 'number'? inc : 1;
      }
    }
    myObject.increment()
    console.log(myObject.value);  / / 1
    myObject.increment(2)
    console.log(myObject.value);  / / 3
Copy the code

Function call pattern

When a function is not a property of an object, it is called as a function. When called as a function, if this is used in the function, this points to the global

Feeling a little abstract? Following the myObject example above, add a double to myObject:

In the double method, there is a helper function, which is obviously not a property of myObject, so it cannot be called a method. So what happens if I use this in this helper function

    myObject.double = function(){
     let helper = function(){
       // Can you guess if this also refers to myObject? The answer is no
       // The value of this.value is undefined
       console.log(Value: 'helper in this.'+this.value);  // undefined

       this.value = add(this.value,this.value)

       console.log('this.value:'+this.value); // undefined + undefined = NaN  
     }
     helper()
   }
   myObject.double()
   console.log(myObject.value) // myobjcet. value has nothing to do with the call to double; the value is still 3
Copy the code

How can the inner function helper also access this in myObject?

Since the double method calls this of myObject, we can set a variable in the double function to receive the value of this, which is then accessed by the inner function helper

   myObject.double = function(){
     let that = this // The solution
     let helper = function(){
       that.value = add(that.value,that.value)
     }
     helper()
   }
Copy the code

Constructor invoke pattern

A function that is created to be used with new is called a constructor function.

When the constructor function is preceded by new, a new object is implicitly created that is attached to the prototype member of the constructor function, and this is bound to the new object.

Just look at an example

    let Quo = function(string){
      this.status = string
    }

    Quo.prototype.getStatus = function(){
      return this.status
    }
    
    let myQuo = new Quo('success')
    console.log(myQuo.getStatus())  / / print success
Copy the code

applyInvocation pattern

First things first: JavaScript is a functional programming language, so functions can call methods.

When A function (let’s say function A) calls the Apply method, the Apply method takes two arguments:

  • The first parameter is to bind tothisThat is, the function AthisPoint to the who)
  • The second argument is the array of arguments to be passed to function A

Here are two examples of how to use the apply parameters:

    let arr = [3.4]
    let sum = add.apply(null,arr) // Sum is 7
Copy the code

In the example above, the add function calls apply. Arr is the array of arguments received by the add function, and NULL indicates that the add function was not assigned this. This is not actually used in the add function, so you don’t need to specify it.

Let’s look at another example where this is specified, followed by the code in the Quo constructor example above:

Start by defining an object, statusObj

    let statusObj = {
      status: 'failed'
    }
    let status = Quo.prototype.getStatus.apply(statusObj) // The status value is failed
Copy the code

Think about it. Why?

If I look at the code above, Status = statusObj; statusObj = this; statusObj = statusObj; So the result is failed.



If you find something wrong, please correct it in time!