Javascript 如何检测对象是否为间隔/超时?

Javascript 如何检测对象是否为间隔/超时?,javascript,node.js,Javascript,Node.js,对于node.js var timer = setInterval(function(){console.log('hi')},1000); var notATimer = {}; var number = 2; detectTimer(timer) //returns true detectTimer(notATimer) //returns false detectTimer(number) //returns false 是否有任何方法可以可靠地确定对象是否为间隔? 此外,如果检测设置

对于node.js

var timer = setInterval(function(){console.log('hi')},1000);
var notATimer = {};
var number = 2;

detectTimer(timer) //returns true
detectTimer(notATimer) //returns false
detectTimer(number) //returns false
是否有任何方法可以可靠地确定对象是否为间隔?
此外,如果检测设置超时的方法也适用于设置超时,则可获得额外的积分。

同时
setTimeout
setInterval
返回一个id引用(在浏览器中)

在节点中,它们返回对
超时
对象的引用

因此,没有真正的方法来确定返回值是来自计时器,还是来自浏览器中某个地方的变量

节点中技术上可以对返回值的构造函数执行
instanceof Timeout
检查,但我个人不喜欢这样做


不过,您可以将计时器实现包装到某个包装对象调用程序中,然后检查哪些对象调用程序将在节点和客户端工作

例如:

class Timer {
    constructor(callback, time) {
         this.timeId = setTimeout(callback, time);
    }
    clear() {
         clearTimeout(this.timeId);
    }
}

const time = new Timer(() => console.log('hi'), 1000);

console.log(time instanceof Timer); // true
在nodejs和return实例中。该构造函数未导出,但您仍然可以访问它并使用它检测计时器对象:

const Timeout = setTimeout(function(){}, 0).constructor;
function isTimer(t) { return t instanceof Timeout; }

如果您不想这样做,您也可以通过测试对象的属性来使用duck类型。

我认为其他人已经提到的常规方法不可能做到这一点。但是,您可以创建一个包装器,如

// Timeout, Interval, whatever
class Interval {
    constructor(...args) {
        this.interval = setInterval(...args); // again, whatever fits your needs
        return this;
    }

    /* ... */
}
如果适用的话

const timer = new Interval(() => console.log('I am an interval'), 1000);

console.log(timer instanceof Interval) // => true (It's an interval)

现在这只是一个基本的例子,但我希望它能给你一个正确的想法。

我建议更改javascript的setTimeout和setInterval函数,我意识到,事实上你也为node.js标记了它,所以这里只有一个javascript答案,因为其他答案处理node.js非常好

window.originalSetTimeout=window.setTimeout;
window.originalClearTimeout=window.clearTimeout;
window.originalSetInterval=window.setInterval;
window.originalClearInterval=window.clearInterval;
window.setTimeout=函数(func,延迟)
{
ret=窗口原始设置超时(func,延迟);
ret+='-超时';
返回ret;
};
window.setInterval=函数(func,delay)
{
ret=窗口原始设置间隔(func,延迟);
ret+='-间隔';
返回ret;
};
window.clearTimeout=函数(timerID)
{
tid=timerID.split('-')[0];
窗口原始清除超时(tid);
};
window.clearInterval=函数(timerID)
{
tid=timerID.split('-')[0];
窗口原始清除间隔(tid);
};
isTimeout=函数(timerID)
{
t=timerID.split('-')[1];
if(t==“timeout”)返回true;
返回false;
}
isInterval=函数(timerID)
{
t=timerID.split('-')[1];
如果(t==“间隔”)返回true;
返回false;
}  
t=setTimeout(函数(){console.log('here');},5000);
if(isTimeout(t))document.getElementById('mess').innerHTML+='
t是超时'; if(isInterval(t))document.getElementById('mess').innerHTML+='
t是一个区间'; p=setInterval(函数(){console.log('Interval here');},5000); if(isTimeout(p))document.getElementById('mess').innerHTML+='
p是一个超时'; if(isInterval(p))document.getElementById('mess').innerHTML+='
p是一个区间';


为什么要这样做?
定时器的类型是
数字
notATimer
是一个
对象
@Nonemoticoner,不能满足一般设置。尽管进行了一次编辑,明确提到了这一点。@Nonemoticoner:
typeof timer
是node中的
“object”
,我不知道该怎么做-但有一种黑客方法,将一个属性添加到setTimeout prototype
prototype.someProp='timer'
,然后检查它,或者更好的做法是听从@Neals answer这个问题是关于node的,而不是DOM api。答案的第一段暗示了这一点,因为node没有为计时器返回整数引用。
setInterval
与DOM api有什么关系
setInterval
返回一个
number
,这是通过
clearInterval()取消时使用的id
DOM API返回一个整数,标识计时器。CommonJSAPI(相同调用)返回一个计时器对象。如果您在浏览器中运行,这是正确的解决方案。@ndugger:很抱歉我的公式太草率了。它应该是“这个问题是关于在NodeJS环境中执行的代码,而不是在具有的DOM环境中执行的代码”。虽然包装器对象可以很好地解决OP面临的问题,但在我看来,这个答案(“否”)并不能真正回答这个问题-P在我看来很好,但这与我的答案是一样的。是的,我也注意到了,但我向你保证,我没有模仿你:PI很高兴我最终能给出答案,但有你^^很乐意帮助。。。我认为?@Neal:)我的答案在节点端和客户端都有效。在我看来,访问对象的构造函数也是“讨厌的”。@Neal:当然,客户端需要一个包装器(这是一个很好的解决方案!),但这不是OP要求的。还有一点是正确的,
Timeout
没有导出是有充分的理由的,解决这些问题可能会给您带来麻烦,但这是唯一真正可靠的方法。在节点v11.5.0上不起作用:“ReferenceError:Timeout未定义”@ekkis-Hm,我现在无法尝试,请使用调试器检查
setTimeout
的返回值好吗?NodeJSIDN中没有
窗口
,我不知道这是针对node的。@GregBorbonus这几乎不清楚。问题中没有明确提及,只是通过标签间接提及,这通常是垃圾邮件和不可靠的。谢谢勒克斯,我编辑了答案以表明这是一个错误。我以前从未想过这是一个问题,但我非常喜欢这个解决方案,最终我会自己使用它。