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
apply
Invocation 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 to
this
That is, the function Athis
Point 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!