JavaScript 类中的 setTimeout() 使用“this”

Posted

技术标签:

【中文标题】JavaScript 类中的 setTimeout() 使用“this”【英文标题】:setTimeout() inside JavaScript Class using "this" 【发布时间】:2011-08-20 03:39:44 【问题描述】:

我正在尝试在 javascript 的类函数中使用 setTimeout()setTimeout() 应该触发同一个类中的另一个方法,所以我传递给它的函数写成window.setTimeout("this.anotherMethod", 4000)。这带来了问题:this 引用了调用对象,在setTimeout() 的情况下它是window。如何使用附件返回对类对象本身的引用?

myObject = function()

this.move = function()
    alert(this + " is running");

this.turn = function()
    alert(this + " is turning");

this.wait = function()
    window.setTimeout("this.run" ,(1000 * randomNumber(1,5)));


this.run = function()
    switch(randomNumber(0,2))
        case 0:
            this.move();
        break;
        case 1:
            this.turn();
        break;
        case 2:
            this.wait();
    

【问题讨论】:

我设置了 = this,并将其用于所有方法,就像魔术一样,为所有回答这个问题的人 +1,非常感谢。 【参考方案1】:

你可以这样做:

 var that = this;
 setTimeout(function () 
     that.doStuff();
 , 4000);

您也可以bind 获取更简洁的代码(正如@Raynos 最初指出的那样):

setTimeout(this.doStuff.bind(this), 4000);

bind 是针对这种编码模式的标准库函数(即从词法上捕获this)。

【讨论】:

@David Dorward:我在点击提交后才意识到这一点。我不应该在早上 5 点发帖。 @Dorward 在编辑答案之前发表了评论。现在是正确的 我一直被困在这个问题上,这似乎解决了我的问题。谢谢。 我在一个实现了单例模式的类中使用了这个答案,它可以工作! @Antoine:很公平,而且 ES5 支持现在可能已经足够广泛,使用它完全不是问题。我将对此进行编辑。【参考方案2】:

您还可以将函数绑定到范围。

setTimeout(this.run.bind(this) ,(1000 * randomNumber(1,5)));

警告Function.prototype.bind 是 ES5

【讨论】:

你可以绑定到任何 js 项目上工作:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… :)【参考方案3】:

this 在 javascript 中可能会出现问题,正如您所发现的那样。

我通常通过在对象内部给this 加上别名来解决这个问题,这样当我需要引用回包含对象时就可以使用别名。

MyObject = function ()

    var self = this;

    // The rest of the code goes here

    self.wait = function()
        window.setTimeout(self.run ,(1000 * randomNumber(1,5)));
    

【讨论】:

我发现 self 是一个最容易引起误解的标识符,尤其是因为它与 this 具有非常相似的含义,正如您所指出的,这意味着其他东西。 这只是一个示例,您可以将其称为 MyObjRef,或者您认为应该使用的任何其他名称。关键是它为您提供了一种获取对象引用的方法。【参考方案4】:
class A

   setTimeout(()=>

       // here this != undefined because of arrow function

  ,500);


【讨论】:

在回答一个老问题时,如果您包含一些上下文来解释您的答案如何提供帮助,那么您的答案将对其他 *** 用户更有用,特别是对于已经有一个已接受答案的问题。请参阅:How do I write a good answer。【参考方案5】:
this.wait = function()
    var self = this;
    window.setTimeout(function()  self.run()  ,(1000 * randomNumber(1,5)));

因此,您将对正在调用 .run 的对象的引用存储在局部变量(“self”)中。

【讨论】:

【参考方案6】:

this 对调用它的上下文很敏感。当您将字符串传递给 setTimeout 时,那是 evaled 在完全不同的上下文中。

您需要保留this 的当前值(通过将其复制到不同的变量)并保持范围(通过不使用(隐含)eval)。

this.wait = function()
    var self = this;
    setTimeout(function ()  self.run() ,
              (1000 * randomNumber(1,5))
              );

【讨论】:

【参考方案7】:

在主 myObject 的顶部,对 this 的当前值进行新的引用:

var self = this;

然后为您的计时器回调创建一个闭包,该闭包使用该新引用而不是 setTimeout 将用作回调中的默认上下文的全局对象:

setTimeout(function() 
    self.run();
, 4000);

【讨论】:

【参考方案8】:
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

func 内部,this 始终引用全局对象。可以将当前对象传入func,

var timeoutID = window.setTimeout(func, delay, this);
function func(that) ...

不幸的是,它在 IE 中不起作用

Note that passing additional parameters to the function in the first syntax does not work in Internet Explorer.

【讨论】:

【参考方案9】:

你可以只使用箭头函数语法:

setTimeout(() => 
     this.doStuff();
 , 4000);

【讨论】:

【参考方案10】:

你试过了吗;

window.setTimeout("myObject.run" ,(1000 * randomNumber(1,5)));

【讨论】:

【参考方案11】:

您可以改用此代码,它适用于所有现代浏览器 -

setTimeout(function(thisObj) thisObj.run();,1000,this);

参考:http://klevo.sk/javascript/javascripts-settimeout-and-how-to-use-it-with-your-methods/

【讨论】:

【参考方案12】:

更短的方式。没有匿名函数。

    var self = this;
    setTimeout(self.method, 1000);

【讨论】:

【参考方案13】:

不建议使用字符串使用 setTimeout 或 setInterval

setTimeout("myFunction()", 5000);

//this is the same as 

setTimeout(function() eval("myFunction()"); , 5000)); //<-- eval == BAD

【讨论】:

【参考方案14】:

遇到了一个更复杂的情况...A类有一个B类型的成员和一个调用setTimeout的方法,该方法调用B类的一个方法。解决如下:

class A 
    constructor(b) 
        this.b = b;
    
    setTimer(interval) 
        setTimeout(this.b.tick.bind(this.b), interval);
    

class B 
    constructor(name)
        this.name = name;
        this.ele = window.document.getElementById('B');
    
    tick() 
        console.log(this);
        this.ele.innerText += ' ' + this.name;
    

在 B.tick 中将 A.b 绑定到 this 并起作用。

这是bind:https://jsfiddle.net/jrme9hyh/的小提琴

还有一个没有bind 的失败:https://jsfiddle.net/2jde8tq3/

【讨论】:

以上是关于JavaScript 类中的 setTimeout() 使用“this”的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript:在另一个 setTimeOut(嵌套 setTimeOut)中的 setTimeOut 以刺激 API 响应不起作用

在javascript中的另一个setTimeout函数中使用setTimeout

JavaScript 的setTimeout 和Angular中的$timeout的區別

如何在javascript中获取所有计时器?

如何为数组中的每个项目评估包含 settimeout 的函数(Javascript)

为啥C没有像javascript中的setTimeout这样的非阻塞睡眠功能