Regarding the pointing problem of this in setTimeout and setInterval

Problem Description

A few days ago, I used a timer when I practiced writing a small example. I found that when the function is passed in setInterval and setTimeout, this in the function will point to the window object, as in the following example:

var num = 0;
function Obj (){
    this.num = 1,
    this.getNum = function(){
        console.log(this.num);
    },
    this.getNumLater = function(){
        setTimeout(function(){
            console.log(this.num);
        }, 1000)
    }
}
var obj = new Obj; 
obj.getNum();//1  打印的是obj.num,值为1
obj.getNumLater()//0  打印的是window.num,值为0

problem causes

From the above example, we can see that the this in the function in setTimeout points to the window object. This is because the code called by setTimeout() runs on an execution environment completely separated from the function in which it is located. This causes the this keyword contained in these codes to refer to the window (or global) object. For details, please refer to MDN setTimeout

Solution

If you want this in setTimeout to point to the correct value, you can use the following three common methods to make this point to the correct value:

1. Store the this of the current object as a variable, and the function in the timer uses the closure to access this variable , as follows:

var num = 0;
function Obj (){
    var that = this;    //将this存为一个变量,此时的this指向obj
    this.num = 1,
    this.getNum = function(){
        console.log(this.num);
    },
    this.getNumLater = function(){
        setTimeout(function(){
            console.log(that.num);    //利用闭包访问that,that是一个指向obj的指针
        }, 1000)
    }
}
var obj = new Obj; 
obj.getNum();//1  打印的是obj.num,值为1
obj.getNumLater()//1  打印的是obj.num,值为1

This method is to put the reference of the current object in a variable, and the function inside the timer can access this variable, and the current object can be obtained naturally.

2. Use the bind() method

var num = 0;
function Obj (){
    this.num = 1,
    this.getNum = function(){
        console.log(this.num);
    },
    this.getNumLater = function(){
        setTimeout(function(){
            console.log(this.num);
        }.bind(this), 1000)    //利用bind()将this绑定到这个函数上
    }
}
var obj = new Obj; 
obj.getNum();//1  打印的为obj.num,值为1
obj.getNumLater()//1  打印的为obj.num,值为1

The bind() method is a method on Function.prototype. When the bound function is executed, the bind method will create a new function and use the first parameter as this when the new function runs. In this example, when the function in setTimeout is called, the bind method creates a new function and passes this into the new function, and the execution result is correct. For the bind method, please refer to MDN bind

3. Arrow functions

var num = 0;
function Obj (){
    this.num = 1,
    this.getNum = function(){
        console.log(this.num);
    },
    this.getNumLater = function(){
        setTimeout(() => {
            console.log(this.num);
        }, 1000)    //箭头函数中的this总是指向外层调用者,也就是Obj
    }
}
var obj = new Obj; 
obj.getNum();//1  打印的是obj.num,值为1
obj.getNumLater()//1  打印的是obj.num,值为1

The arrow function in ES6 completely fixes the pointing of this. This always points to the lexical scope, which is the outer caller obj, so this problem can be easily solved by using the arrow function.

The above three methods are relatively commonly used. Of course, if you use the call or apply method instead of the bind method, the result is correct, but the call method will be executed immediately after the call, so there will be no delay effect. Timing The device is useless, so it is recommended to use the above method to pass this into setTimeout and setInterval.

original address

Guess you like

Origin blog.csdn.net/qq_39327418/article/details/90703198