假设你有这个功能序列(JavaScript)....
A(function(){
console.log('done')
})
function A(done) {
a()
B(D, done)
}
function B(x, y) {
x(function(){
c()
C(y)
d()
})
}
function C(z) {
g()
setTimeout(z, 1000)
}
function D(z) {
h()
setTimeout(z, 2000)
}
function a() {
b()
c()
}
function b() {
// ... sync stuff
}
function c() {
e()
// ... sync stuff
f()
}
function d() {
// ... sync stuff
}
尝试使它具有一种复杂的调用堆栈。
我想知道的是调用堆栈在不同时间点的样子。例如,c();C(y);d()
序列。当调用c()
时,在该级别调用的下一个函数是C()
。所以看起来它会推到堆栈上(在评估c()
之前),C()
是返回位置。然后它去e()
和f()
(暂时忽略它)。然后它检查调用堆栈并返回C()
。然后同样的过程。但由于C()
是异步的,所以在d()
完成之前它会进入C()
。所以它是这样的:
c c c c c c c ...?
C C C C C / \
e e f C d
f
这是我在尝试绘制调用堆栈时的想法。好像它会形成一棵树。现在想象多个异步进程在同一时间开始。然后它就像树的多个分支。所以不是调用堆栈,而是调用树。这让我终于质疑调用堆栈的评估方式。当序列中的下一个函数被推送到调用堆栈时,以及它们如何更新/删除最后完成的函数并找到返回调用堆栈/树中下一个位置的方法。
想知道你是否可以指出任何可能描述这个的资源,或者甚至可能解释调用堆栈在我上面描述的例子中的样子。
当你调用一个函数时,你会在堆栈上推送一个返回地址,而不是下一个要调用的函数。然后被调用的函数将在堆栈上创建自己的框架(您可以考虑该框架的返回地址部分或与框架分离,具体取决于您如何看待它。当函数返回时,它将弹出其框架并返回到返回地址(也将隐式或显式地弹出返回地址 - 详细信息取决于CPU / VM体系结构。
因此,对于您的示例,随着时间的推移调用堆栈看起来更像
c c c c c C C
e f g