как setTimeout предотвращает потенциальный переполнение стека

Пример :

var list = readHugeList();

var nextListItem = function() {
    var item = list.pop();

    if (item) {
        setTimeout( nextListItem, 0);
        // ^^^^^^^^ this line
    }
};

Как использование setTimeout предотвращает потенциальный переполнение стека? Я понимаю концепцию как очереди событий, так и стека, но мне трудно соединить их.

 devnull6902 июн. 2016 г., 15:15
Если вы просто вызвали nextListItem из nextListItem, стек будет расти с каждым вызовом, пока вы не достигнете критериев выхода (список пуст). Когда вы используете setTimeout, внешняя функция завершится и будет удалена из стека, тогда только внутренний вызов функции будет в стеке

Ответы на вопрос(2)

Решение Вопроса

Заданное время ожидания не приведет к переполнению стека, поскольку оно асинхронно. Он просто поместит обратный вызов в очередь событий, а не заблокирует выполнение.

В первом случае:

setTimeout просто помещает обратный вызов в очередь событий, и родительская функция завершает работу без загрузки стека.
Несмотря на то, что тайм-аут равен 0 мс, он будет вызван в следующем цикле событий, таким образом, не блокируя код при выполнении.

var nextListItem = function() {
    var item = list.pop();

    if (item) {
         setTimeout( nextListItem, 0);
    }
};

Во втором случае:

Родительский вызов дочерней функции, помещающей новую запись в стек, даже если родители не очищены из стека.
В конце концов, более рекурсивные вызовы могут разрушить стек.

var nextListItem = function() {
        var item = list.pop();

        if (item) {        
           nextListItem();
        }
    };

setTimeout(, 0) запланировать запуск функции после ее завершения.nextListItem() не будет вызываться рекурсивно, но вызывается снова средой JS.

Если вы делаетеvar r() = function() { r(); }; функция вызывает себя и переполняет стек. Если вы делаетеvar r() = function() { setTimeout(r, 0); }; затемr() будет запланировано запустить послеr() заканчивается, и он будет работать вечно.

Это причина для использованияsetTimeout(, 0) вместоwhile или жеfor перебрать список. Это позволяет браузеру обрабатывать другие события до следующего вызоваnextListItem, Если список длинный, это позволяет избежать блокировки браузера на длительное время. С другой стороны, еслиnextListItem манипулирует DOM, это намного медленнее, чем делать это за один раз.

Ваш ответ на вопрос