关于javascript:setTimeout中的变量表示它未定义,但在外部定义时

Variable inside setTimeout says it is undefined, but when outside it is defined

本问题已经有最佳答案,请猛点这里访问。

我要上课。我需要在超时内做一些HTTP工作。我面临的问题是超时内的HTTP变量一直说它是未定义的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export class MyClass {

    http:Http:

    constructor(private http:Http) {
        this.http = http;
    }

    sendFriendRequest(){

    this.http.post( ...//http variable is defined here
           setTimeout(function(){
               this.http.post(...  //http is not defined here
        }
   }
}


这是因为setTimeout中的回调函数在不同的词汇环境中。这就是为什么在ES6+中可以使用=>定义函数。这样,函数中的代码与函数共享相同的作用域。

要解决这个问题,您可以使用es6+语法,其中使用(a,b,args) => {...}而不是function(a,b,args) {...}

1
2
3
setTimeout( () => {
  this.http.post(...)
});

或使用ES5语法:

1
2
3
4
5
var root = this;

setTimeout(function(){
    root.http.post(...)
}

希望这有帮助!


在javascript中,this关键字用于访问调用函数的context。除非在当前作用域中设置了'use strict'标志,否则,无论是使用.methodName()语法还是不使用该语法来调用javascript中的函数,都会使用上下文来调用函数。

当在没有类似上下文的情况下调用函数时:

1
myFunction()

上下文由运行时假定为全局窗口对象(除非设置了'use strict'标志,在这种情况下上下文将不定义)。

注意:当对Babel这样的蒸腾器使用ES6时,在输出中默认设置严格模式。

当对函数的引用保存在对象上时,可以使用点语法以对象作为"this"的上下文来调用该函数。

1
2
3
4
5
6
var myObj = {
    myFunc: function(){}
};

// myFunc invoked like this, the value of 'this' inside myFunc will be myObj.
myObj.myFunc();

操纵"this":

调用与应用

您可以通过使用.call或.apply方法调用函数来更改其上下文。在这种情况下,您有一个匿名函数,它不是由您调用的,而是由setTimeout函数调用的。正因为如此,你将无法利用。打电话或。申请。

束缚

相反,您可以使用.bind方法创建一个具有自定义上下文的新函数。通过对匿名函数调用.bind(),将返回一个新函数,该函数将您的自定义上下文绑定到"this"。这样就可以将自定义绑定函数作为数据传递给setTimeout。

1
2
3
setTimeout(function(){
   // your code.
}.bind(this), 1000);

现在,在匿名函数内部,"this"关键字将绑定到正确的值。

词汇"这个":

但是,在ES6中,使用箭头函数时,有关"this"的规则会发生更改。如果使用此语法,您将看到"this"的上下文将保持与当前作用域中的上下文相同。

1
2
3
setTimeout(() => {
    // Hey I can access 'this' in here!
}, 1000);

保存引用:

如果您查看babel编译的输出,您将看到babel通过保存对"this"的引用来跟踪上下文,其中包括"this1"、"this2"等等。

要使用此方法,只需声明一个新变量(通常使用"that"或"self"),并在匿名函数中使用它访问值,如下所示:

1
2
3
4
var self = this;
setTimeout(function(){
    self.http.post...
});

希望这有帮助。

为了得到更多的解释,developer.mozilla.org有一篇很好的文章描述了函数范围内"this"的行为。


您应该在这里使用arrow函数,以保持这个函数的存在。

1
2
3
setTimeout(()=>{
   this.http.post(...  //http is not defined here
})

这样,函数内部的this与外部上下文绑定。同:

1
2
3
setTimeout(function(){
    this.http.post();
}.bind(this));

使用function(){...时,setTimeout内的this不同。

本期最流行的两种方式:

1)使用额外变量存储在"this"之外

1
2
3
4
5
6
var that = this;
this.http.post( ...//http variable is defined here
           setTimeout(function(){
               that.http.post(...  //http is not defined here
        }
   }

2)使用箭头功能

1
2
3
4
5
this.http.post( ...//http variable is defined here
           setTimeout(() => {
               that.http.post(...  //http is not defined here
        }
   }

第一种方法是旧的ES5,您不需要任何编译器,对于ES6版本(2),您需要使用类似Babel的东西。

有关arrow函数的更多信息,请访问:https://babeljs.io/docs/learn-es2015/