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

时间:2016-03-24 20:51:06

标签: javascript angular

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

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
        }
   }
}

4 个答案:

答案 0 :(得分:34)

原因是setTimeout 中的回调函数处于不同的词汇环境。这就是ES6 +功能可以使用=>定义的原因。这样函数中的代码与函数共享相同的范围。

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

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

或使用ES5语法:

var root = this;

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

希望这有帮助!

答案 1 :(得分:7)

在JavaScript中,this关键字用于访问调用函数的context。除非您使用.methodName()语法调用它们,否则始终使用上下文调用JavaScript中的函数,除非在当前作用域中设置了'use strict'标志。

在没有像这样的上下文的情况下调用函数时:

myFunction()

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

注意:将ES6与像Babel这样的转换器一起使用时,默认情况下会在输出中设置严格模式。

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

var myObj = {
    myFunc: function(){}
};

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

操纵'这'

致电并申请

您始终可以通过使用.call或.apply方法调用函数来更改函数的上下文。在这种情况下,您有一个匿名函数,您不会调用该函数,而是由setTimeout函数调用。因此,您无法利用.call或.apply。

<强>绑定

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

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

现在在匿名函数里面&#39;这个&#39;关键字将绑定到正确的值。

Lexical&#39; this&#39;

然而,在ES6中,当使用箭头功能时,关于“&#39;这个&#39;更改。如果您使用此语法,您将看到&#39; this&#39;将与当前范围内的任何内容保持一致。

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

保存参考:

如果你查看Babel的编译输出,你会看到Babel通过保存对这个&#39;这个&#39;的引用来跟踪上下文。与_this1,_this2等等。

要使用此方法,您只需声明一个新变量(它常用于使用&#39;或者自己&#39;)并在匿名函数中使用它来访问该值像这样:

var self = this;
setTimeout(function(){
    self.http.post...
}); 

希望这会有所帮助。

有关详细说明,developer.mozilla.org有good article describing the behavior of 'this' inside a functions scope

答案 2 :(得分:6)

你应该在这里使用箭头功能,以保持这种存在。

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

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

相同
setTimeout(function(){
    this.http.post();
}.bind(this));

答案 3 :(得分:2)

使用this

setTimeout内的function(){...不一样

这个问题有两种最常用的方式:

1)使用额外的变量存储在“this”之外

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

2)使用箭头功能

this.http.post( ...//http variable is defined here
           setTimeout(() => {
               that.http.post(...  //http is not defined here
        }
   }

第一种方式是旧的ES5,你不需要任何编译器,对于ES6版本(#2),你需要使用像babel这样的东西。

详细了解箭头功能&amp; babel:https://babeljs.io/docs/learn-es2015/