我将假设您在单线程上下文中运行它(例如浏览器1或 NodeJS)。
如果是这样,这两种情况之间的区别在于 C 是通过间接递归调用的,因此一个简单的状态变量可以告诉您是否发生了这种情况。
最简单的形式当然是计数器:
var callstoC = 0;
function C() {
++callsToC;
// ...code here that checks `callsToC`: If it's `1`, it's not recursive;
// if it's `> 1`, it's recursive (indirectly or directly)
--callsToC;
}
您可以使它比跟踪状态更复杂(例如使用数组来记住每个调用的参数是什么,以防万一——例如,用于报告目的)。
显然,所有离开函数的路由正确记录你离开函数是关键。
现场示例:
function hook(selector, event, handler) {
var elements = document.querySelectorAll(selector);
for (var n = 0; n < elements.length; ++n) {
elements[n].addEventListener(
event,
handler,
false
);
}
}
hook("#btnA, #btnB, #btnD", "click", function() {
console.log(this.id + " calling C");
C(this.id == "btnD");
});
var callsToC = 0;
function C(flag) {
++callsToC;
console.log("C called with flag = " + flag + ", callsToC = " + callsToC);
if (flag) {
D();
}
console.log("C about to decrement and exit, callsToC = " + callsToC);
--callsToC;
}
function D() {
console.log("D calling C");
C(false);
console.log("D done");
}
.as-console-wrapper {
max-height: 80% !important;
}
<input type="button" id="btnA" value="A">
<input type="button" id="btnB" value="B">
<input type="button" id="btnD" value="D">
callsToC
在评论中,您有一个全球性的担忧。它不一定是,我不会让它成为全球性的,甚至不会像C
; 我只是不想使示例复杂化。我会像这样使它真正私有给C:
var C = (function() {
var callsToC = 0;
return function C() {
// ...
};
})();
1虽然浏览器支持多线程(通过网络工作者),但它们不支持在多线程中使用相同的功能;每个线程都有自己的全局上下文。