26

假设某人(邪恶)为我们设置了一个带有 的计时器setInterval,但我们不知道它的 ID(我们没有对该对象的引用,setInterval 正在返回,也没有它的值)

(function(){
  setInterval(function(){console.log('pwned')},
              10000)
})();

有没有办法,如何清除?是否可以通过其他方式访问计时器?或者至少特别是浏览器/javascript引擎?

David Flanagan 在他的大 JSTDG 中也谈到了类似的话题。 setInterval() method, use in malicious code索引中的键指向

... 一些浏览器会检测到重复的对话框和长时间运行的脚本,并为用户提供停止它们的选项。但是恶意代码可以使用诸如 setInterval() 之类的方法来加载 CPU,并且还可以通过分配大量内存来攻击您的系统。Web 浏览器没有通用的方法可以防止这种笨拙的攻击。实际上,这在 Web 上并不是一个常见的问题,因为没有人会返回从事这种脚本滥用的站点!

4

4 回答 4

49

通过快速测试,所有主要浏览器(最新的 Chrome、Firefox 和 IE)都给出了非常小的数字作为 ID,因此只需“盲目地”循环所有可能的数字就可以了:

function ClearAllIntervals() {
    for (var i = 1; i < 99999; i++)
        window.clearInterval(i);
}

完整示例:

window.onload = function() {
    window.setInterval(function() {
        document.getElementById("Tick").innerHTML += "tick<br />";
    }, 1000);
    window.setInterval(function() {
        document.getElementById("Tack").innerHTML += "tack<br />";
    }, 1000);
};

function ClearAllIntervals() {
    for (var i = 1; i < 99999; i++)
        window.clearInterval(i);
}
#Placeholder div { width: 80px; float: left; }
<button type="button" onclick="ClearAllIntervals();">Clear All</button>
<div id="Placeholder">
    <div id="Tick"></div>
    <div id="Tack"></div>
</div>

这将停止所有间隔,当然不能在不知道其 ID 的情况下停止特定间隔。

正如您可以自己测试的那样,它应该适用于上述所有主要浏览器。

于 2011-07-27T11:15:44.443 回答
13

好吧,Chrome 中的经验试验表明,setInterval每次调用都会返回一个递增的数字。因此,如果您确定您的 setInterval 是最后一组,则以下设置将起作用:

function clearLastInterval () {
  var i = setInterval (function () {}, 10000);
  clearInterval (i-1);
  clearInterval (i);
}

我不确定我会推荐这个;-)

于 2011-07-27T11:05:16.020 回答
8

我尝试了#Shadow Wizard 建议的方法,它可以清除间隔。但是,这种方法后来产生了副作用。在我的特殊情况下,我在清除所有间隔后无法使用 jquery.fadeTo() 。

我确定的方法是更清洁的解决方案,即重新定义 setInterval 方法并将间隔 id 保存在重新定义的方法中。如此处所示,我将 id 放入一个数组中,然后将它们全部清除。通过稍微改进存储数组的结构,您可以标记它们并有选择地清除它们。

var intervalTracking = new Array();
var intervalCount=0;

window.oldSetInterval = window.setInterval;
window.setInterval = ( function(func, interval) {
    var interval = oldSetInterval(func, interval);
    intervalTracking[++intervalCount]=interval;
    return interval;
});

function clearAllIntervals() {
    for (var i = 0 ; i <= intervalCount ; i++) {
    window.clearInterval( intervalTracking[i] );
    }
}

这似乎有效!

于 2011-10-05T15:36:41.563 回答
0

我通过使用 localstorage 解决了这个问题,将 setInterval 的 id 保存在那里,然后稍后再拿起它以清除该间隔..

于 2015-09-11T15:15:13.443 回答