Я думаю, что главное недоразумение заключается в «callstack» здесь: Давайте возьмем это:
(function A() {
(function B() {
setTimeout(function C() {
(function D() { })();
});
})();
})();
Прежде всего, код инициализируется, вызывается A и вызывается B, стек вызовов выглядит следующим образом:
[init] -> A -> B
Теперь время ожидания устанавливается. Поскольку никакого кода не осталось, стек вызовов раскручивается и становится пустым.
Теперь Через некоторое время , таймер вызовет обратный вызов:
[timer] ->
И тогда это вызовет C:
[timer] -> C
внутри C, D будет называться:
[timer] -> C -> D
поскольку код не остался, стек вызовов снова раскручивается. Как видите, A и B больше не находятся в стеке вызовов, они оставили его давным-давно . Поэтому
setTimeout был вызван в локальном контексте выполнения. Разве нам не нужно только ждать, пока все кадры выше локального контекста выполнения, где был вызван setTimeout, будут удалены?
Не имеет особого смысла, потому что "контекст был setTimeout" был выполнен в является самый верхний контекст выполнения.
Обратите внимание, что контексты выполнения имеют родительский контекст выполнения, который будет существовать до тех пор, пока живут его дочерние элементы (замыкание), однако это не имеет ничего общего с стеком вызовов.