2016-03-24 51 views
10

我有一个类。我需要在超时时间内完成一些http工作。我面临的问题是超时内的http变量一直说它是未定义的。setTimeout里面的变量说明它是未定义的,但是当它在外面定义时

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

这是因为'这个'上下文:http://stackoverflow.com/questions/2130241/pass-correct-this-context-to-settimeout-callback – nikoskip

+4

我们真的需要4个答案,这个问题基本上都是这样说的“使用箭头函数来获得正确的'this' context”? –

+3

@MarkRajcok是的,有3个答案是不够的! –

回答

19

这样做的原因是,里面的setTimeout 回调函数是在不同的词汇环境。这就是为什么可以使用=>来定义ES6 +功能的原因。这是为了使函数中的代码与函数共享相同的范围。

为了解决这个问题,您可以使用ES6 +语法,其中代替function(a,b,args) {...}你可以使用(a,b,args) => {...}

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

或与ES5语法:

var root = this; 

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

希望这有助于!

6

你应该在这里使用箭头函数来保存这个。

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

在这样做时,this函数的内部被绑定到外部环境。这是一样的:

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

它不是thissetTimeout同样,当您使用function(){...

2点最流行的针对此问题的方法:

1)使用额外的变量外存储“本”

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的东西。

找到更多关于箭头功能&巴贝尔在这里:https://babeljs.io/docs/learn-es2015/

+0

感谢您的信息! – user2924127

3

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

当一个函数被没有像这样的上下文中调用:

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或方法。适用调用它改变功能的情况下。在这种情况下,你有一个匿名函数,它不会被你调用,而是被setTimeout函数调用。因此,您将无法利用.call或.apply的优势。

绑定

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

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

现在里面的匿名函数里'this'关键字会被绑定到正确的值。

词汇 '这个':

在ES6然而,使用箭头功能大约 '这个' 变化的规则时。如果你使用这个语法,你会看到'this'的上下文将保持与当前范围内的任何内容相同。

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

保存参考:

如果你看一下编译后的输出从巴别塔,你会看到巴贝尔通过保存引用到“本”与_this1,_this2等等跟踪上下文。

要使用此方法自己只是声明了一个新的变量(这是通常使用“是”或“自我”),并使用它访问值的匿名函数里面,像这样:

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

希望这有助于。

更多解释developer.mozilla.org有good article describing the behavior of 'this' inside a functions scope

+0

感谢您的好评! – user2924127

相关问题