JavaScript-когда именно стек вызовов становится "пустым"?
Я прочитал несколько сообщений / так потоков на цикле событий, и в соответствии с статья MDN,
когда стек пуст, сообщение извлекается из очереди и обработанный.
как Новичок JS, то, что я все еще смущен, - когда именно стек вызовов становится "пустым"? Например,
<script>
function f() {
console.log("foo");
setTimeout(g, 0);
console.log("foo again");
}
function g() {
console.log("bar");
}
function b() {
console.log("bye");
}
f();
/*<---- Is the stack empty here? */
b();
</script>
правильный порядок выполнения foo
-foo again
-bye
- bar
.
но сегодня я начал думать: не является ли стек технически пустым сразу после выхода из f()
звонок? Я имею в виду, что в этот момент мы не находимся внутри какой-либо функции, и мы не начали никакого нового выполнения, поэтому не должны setTimeout
сообщение вызова (которое было немедленно поставлено в очередь) обрабатывается, прежде чем перейти к b()
, и отдавая приказ foo
-foo again
-bar
- bye
?
что делать, если у нас есть миллион строк кода или некоторые интенсивные вычисления казнили и то setTimeout(func, 0)
просто сидит в очереди так долго?
4 ответов
хотя блок кода внутри <script>
теги не завернуты в явную функцию, может быть полезно думать о ней как о глобальной функции, которую браузер сообщает среде выполнения javascript для выполнения. Таким образом, стек вызовов не пуст, пока не будет выполнен код в блоке скрипта.
когда текущая часть Javascript, которая выполняется, закончена и не имеет более последовательных инструкций для выполнения, тогда и только тогда JS engine вытащит следующий элемент из очереди событий.
Так, в вашем примере:
f();
b();
// JS is done executing here so this is where the next item will be
// pulled from the event queue to execute it
Javascript однопоточен, что означает, что текущий поток Javascript запускается до завершения, выполняя все инструкции в последовательности, пока он не достигнет конца кода. Тогда и только тогда она тянет за собой следующую. элемент из очереди событий.
вот некоторые другие ответы, которые могут помочь Вам разобраться:
Как Работают Таймеры Javascript
как JavaScript обрабатывает ответы AJAX в фоновом режиме? (целая куча ссылок на цикл событий в этом посте)
нужно ли мне беспокоиться об условиях гонки с асинхронным Javascript?
могут ли обработчики событий JS прерывать выполнение еще один куратор?
лучший способ, который я могу придумать, чтобы объяснить это, - это то, что стек вызовов не пуст, пока код не завершит выполнение всех соответствующих путей. SetTimeout 0 просто толкает ваш код в конец стека.
когда код запускается во время выполнения, все, что будет be run является частью стека вызовов, порядок будет скорректирован на основе порядка, вызываемого вещами, и любых таймаутов / интервалов / асинхронных методов, которые вызываются.
некоторые примеры:
function foo() {
console.log('foo');
}
function bar() {
baz();
console.log('bar');
}
function baz() {
setTimeout(function() { console.log('timeout') }, 0);
console.log('baz');
}
foo();
baz();
// call stack ends here, so, timeout is logged last.
// in console
// foo
// baz
// timeout
как вы можете видеть, bar не входит в стек выполнения, потому что он не вызывается. Если у нас есть HTML:
<div onclick="bar()">Bar runs</div>
когда вы нажмете на этот div, вы увидите baz
, bar
, потом timeout
вошел в консоль, потому что тайм-аут всегда нажимается до конца текущего стека процессов / вызовов.
надеюсь, это объяснение поможет!
самое простое возможное объяснение: когда весь синхронный код в текущем скрипте, функции или обработчике событий закончит работу.
прямо ответить: "А что если у меня есть миллионы строк...- Да, ваше setTimeout
вызов застрял в очереди и будет ждать своей очереди.