2013-01-22 32 views
1

我正在試驗JavaScript,僅用於學習目的,我正在編寫一個forEach迭代器,它可以遍歷嵌套數組或其他任何包含length property的可迭代對象。遞歸迭代器上的最大調用堆棧大小錯誤

這是我寫的:

var forEach = function(obj, callback, options) { 
    var options = options || {}; 
    var context = options.context || this;  

    if(!isEmpty(obj)) { // isEmpty function just evaluates `return !(!!obj.length);` 
    for(var x = 0; x < obj.length; x++) { 
     if(!isEmpty(obj[x]) && options.deep === true) { 
     forEach.call(context, obj[x], callback, options); 
     continue; 
     } 
     callback.call(context, obj[x]); 
    } 
    } 
}; 

如果我通過一個嵌套的數組,我得到RangeError: Maximum call stack size exceeded

forEach(['a', 'b', ['c', 'd']], function(x) { 
    console.log(x); 
}, { deep: true }); 

但這似乎只如果我在obj[x]

檢查length屬性發生

如果我替換:

if(!isEmpty(obj[x]) && options.deep === true) { 

爲:

if((obj[x] instanceof Array) && options.deep === true) { 

我會奇蹟般地工作。 Hovewer,不僅Arrays有一個長度屬性。 String有它,所以它不是一個廣泛的方法。

如何防止RangeError但仍檢查length property

編輯:我上運行的NodeJS v0.8.12的例子

+0

考慮到' 'A'[0] [0] [0] [0] [0] [0] [0] ...'是有效的循環往復,和每個值都是'string'類型。如果類型是'string',那麼你不應該遞歸迭代它。 – mellamokb

+0

@mellamokb是的,我想這更有意義:) – jviotti

+0

@mellamokb請張貼您的建議作爲答案,以便我可以接受它 – jviotti

回答

0

考慮到'a'[0][0][0][0][0][0][0]...是有效的循環往復,每一個值的類型string。如果類型是string,那麼你不應該遞歸迭代它。還要注意,function對象具有length屬性,並且function參數可以是自我引用function本身。這會導致另一個無限遞歸。我認爲,不同類型的處理可能更有意義,而不是試圖開發一個全面的功能。

您也可能有一個maxLevel屬性限制遞歸的深度,默認值爲10。這種方式無限遞歸不應該是容易的。

forEach(['a', 'b', ['c', 'd']], function(x) { 
    console.log(x); 
}, { deep: true, maxLevel: 10 }); 

var forEach = function(obj, callback, options, level) { 
    var options = options || {}; 
    var context = options.context || this; 

    if (!level) level = 1; 
    if (!options.maxLevel) options.maxLevel = 10; 

    if (level > options.maxLevel) return; 
    ... 
     forEach.call(context, obj[x], callback, options, level + 1); 
    ... 
} 

演示:http://jsfiddle.net/bjpx5/

相關問題