通过setInterval事件调用类原型方法

And*_*res 27 javascript

我有一个简单的JavaScript类.

此类的一种方法是使用setInterval函数设置计时器.每次事件触发时我想调用的方法都在同一个类中定义.

问题是,如何将此方法作为参数传递给setInterval函数?

一次尝试是setInterval('this.showLoading(),100).但是不起作用.这个方法访问类属性,所以我需要'this'引用.

这是示例代码:

    function LoadingPicture(Id)
    {
        this.imgArray = null;
        this.currentImg = 0;
        this.elementId = Id;
        this.loadingTimer = null;
    }


   LoadingPicture.prototype.showLoading = function()
    {
        if(this.currentImg == imgArray.length)
            currentImg = 0;

        document.getElementById(this.elementId).src = imgArray[this.currentImg++].src;
    }


    LoadingPicture.prototype.StartLoading = function()
    {
        document.getElementById(this.elementId).style.visibility = "visible";
        loadingTimer = setInterval("showLoading()", 100);
    }
Run Code Online (Sandbox Code Playgroud)

Lil*_*ver 37

setInterval可以直接使用函数,而不仅仅是字符串. https://developer.mozilla.org/en/DOM/window.setInterval

loadingTimer = setInterval(showLoading, 100);
Run Code Online (Sandbox Code Playgroud)

但是,为了获得最佳的浏览器兼容性,您应该使用带有显式引用的闭包:

 var t = this;
 loadingTimer = setInterval(function(){t.showLoading();}, 100);
Run Code Online (Sandbox Code Playgroud)


bob*_*nce 21

loadingTimer = setInterval("this.showLoading()", 100);
Run Code Online (Sandbox Code Playgroud)

首先,不要对setInterval/Timeout使用字符串参数.它的使用方式与使用方式相同eval,并且可能会在将来因CSP安全限制而失败.所以与其:

loadingTimer = setInterval(this.showLoading, 100);
Run Code Online (Sandbox Code Playgroud)

但是,正如您所说,这将失去所有者引用,因此被调用的函数将看不到正确的this.在将来(新定义的ECMAScript第五版)中,您将能够将该函数绑定到其所有者function.bind:

loadingTimer = setInterval(this.showLoading.bind(this), 100);
Run Code Online (Sandbox Code Playgroud)

如果您function.bind为尚未拥有它的浏览器实现自己(请参阅本答案的底部),您可以立即使用此语法.

否则,您将需要使用显式闭包,如刚刚发布的计算机语言学家示例.


Oth*_*rew 5

以上回答都可以接受。我只是想补充一点, 的绑定this也可以通过使用箭头函数来解决。例如,这些都是等价的。然而,在使用箭头函数时,词法作用域是保持不变的:

 // Arrow function - my preferred method
 loadingTimer = setInterval(() => this.showLoading, 100);

 // .bind method
 loadingTimer = setInterval(this.showLoading.bind(this), 100);

 // Other method
 var t = this;
 loadingTimer = setInterval(function(){t.showLoading();}, 100);
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助:D