当前位置: 首页 > 知识库问答 >
问题:

变量在setTimeout内部表示它未定义,但在setTimeout外部表示它已定义[duplicate]

葛景龙
2023-03-14

我有课。我需要在超时内做一些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
        }
   }
}

共有3个答案

伊光赫
2023-03-14

您应该在这里使用箭头函数,以保留它的存在。

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

这样做时,函数内部的this被绑定到外部上下文。它与以下内容相同:

setTimeout(function(){
    this.http.post();
}.bind(this));
狄海
2023-03-14

在JavaScript中,this关键字用于访问调用函数的context。无论使用.methodName()语法或不使用它调用JavaScript中的函数,都将使用上下文调用函数,除非在当前作用域中设置了“use strict”标志。

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

myFunction()

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

注意:当使用ES6与像Babel这样的transpiler时,输出中默认设置了严格模式。

当对一个函数的引用保存在一个对象上时,您可以使用点语法将该对象作为“this”的上下文调用该函数。

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。

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

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

词汇“this”:

然而,在ES6中,当使用箭头函数时,关于“this”的规则发生了变化。如果您使用这个语法,您将看到“this”的上下文将与当前范围中的上下文保持相同。

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

保存引用:

如果您查看Babel的编译输出,您将看到Babel通过使用_this1、_this2等保存对“this”的引用来跟踪上下文。

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

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

希望这有帮助。

关于更多的解释,Developer.mozilla.org有一篇很好的文章描述了“this”在函数范围内的行为。

百里承业
2023-03-14

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

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

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

或使用ES5语法:

var root = this;

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

希望这有帮助!

 类似资料:
  • 我订阅了一个方法中的一个可观察的,需要在另一个方法中取消订阅。从一个初始化函数调用子计数器()方法,其内容工作正常。 当我调用我的touchActivate()函数时,它包含一个对存储的变量的unsubscribe函数,但是它会抛出一个错误,因为未定义。控制台日志记录返回一个未定义的对象。 在类的顶部,我定义了一个变量:

  • 我只是想学习Angular 2(特别是Angular 8),就我的一生而言,我不明白为什么类变量在类函数中是“未定义”的,但如果我用ES6风格编写函数,它是可以访问的。 我尝试在构造函数中设置,但这没有意义。 一旦调用HandleClickStart,每1.5秒输出一次NaN。为什么????我本以为是1 2 3...... 通过这种方式实现handleClickStart,可以获得预期的结果: 但

  • 外部定义 有时候创建一个由多个不同检出得到的工作拷贝是非常有用的,举个例子,你或许希望不同的子目录来自不同的版本库位置,或者是不同的版本库。你可以手工设置这样一个工作拷贝—使用svn checkout来创建这种你需要的嵌套的工作拷贝结构。但是如果这个结构对所有的用户是很重要的,每个用户需要执行同样的检出操作。 很幸运,Subversion提供了外部定义的支持,一个外部定义是一个本地路经到URL的影

  • 我正在使用Firebase fiRecovery来保存数据。我想检索用户所在的城市,并根据它,从firest中检索特定数据并设置RecyclView。问题是:当我进行查询时,我不能在OnCompleteListener之外获取变量(城市)。在(setUpRecyclView())中(userCity)下面的代码中是“”,以及OnCompleteListener之外的任何地方。我能做什么??这是我的

  • 问题内容: 在jQuery的核心风格指南建议两种不同的方法来检查一个变量是否被定义。 全局变量: 局部变量: 特性: 为什么jQuery为什么对全局变量使用一种方法而对局部变量和属性使用另一种方法? 问题答案: 对于未声明的变量,将返回字符串文字,而身份检查将触发错误 “未定义foo” 。 对于局部变量(您 知道 已在某处声明),不会发生此类错误,因此进行身份检查。

  • 问题内容: 我想创建一个类,作为的内部类,但是我想写下外部文件。 我怎样才能做到这一点? 这将是很多内部类,而文件将是 巨大的 。 更新 我真正想做的是定义十个类,它们只能由一个类访问。所有这些都在同一包内定义。 谢谢。 问题答案: 将所有类放入包中,并将这些类定义为包私有。 注意没有关键字吗?如果创建类Hello的实例在包中,则您将只能创建该实例的实例。