16.下面的遞歸代碼在數組列表偏大的情況下會導致堆棧溢出。在保留遞歸模式的基礎上,你怎么解決這個問題?
var list = readHugeList(); var nextListItem = function() { var item = list.pop(); if (item) { // process the list item... nextListItem(); } };
潛在的堆棧溢出可以通過修改nextListItem
函數避免:
var list = readHugeList(); var nextListItem = function() { var item = list.pop(); if (item) { // process the list item... setTimeout( nextListItem, 0); } };
堆棧溢出之所以會被消除,是因為事件循環操縱了遞歸,而不是調用堆棧。當 nextListItem
運行時,如果 item
不為空,timeout函數(nextListItem
)就會被推到事件隊列,該函數退出,因此就清空調用堆棧。當事件隊列運行其timeout事件,且進行到下一個 item
時,定時器被設置為再次調用 nextListItem
。因此,該方法從頭到尾都沒有直接的遞歸調用,所以無論迭代次數的多少,調用堆棧保持清空的狀態。