我上课了。我需要在超时内做一些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
}
}
}
答案 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/