【问题标题】:"Too much recursion" when using recursive function from within a namespace在命名空间中使用递归函数时“递归过多”
【发布时间】:2012-11-05 07:50:08
【问题描述】:

我在 javascript 中使用递归方法,它工作得非常好,直到我把它放在一个命名空间中。该函数从数组中返回一个元素,该元素具有给定的quoteproduct id 作为它的id 属性。这是一个嵌套数组,这就是函数递归的原因。这是函数声明:

QuoteProductService.getQuoteProduct = function (quoteproductid) {
    var founditem = null;
    $.each(QuoteProductService.QuoteProductConfigurations, function (index, item) {
        if(item.id == quoteproductid) {
            founditem = item;
            return false; // break the $.each if an item is found
        } else {
            founditem = QuoteProductService.getQuoteProduct(item.children, quoteproductid);
            if(founditem != null) return false; // break the $.each if an item is found
        }
    });
    return founditem;
}

这就是我声明命名空间的方式:

var QuoteProductService = QuoteProductService || {};

这是我在函数中使用的命名空间中的数组:

QuoteProductService.QuoteProductConfigurations = [];

该数组在页面加载时填充。

现在,每当我调用该函数时,都会收到“递归过多”错误。我究竟做错了什么 ?同样,在我将函数和数组放入命名空间之前,这个函数就起作用了。

【问题讨论】:

  • QuoteProductService.getQuoteProduct 只需要 1 个参数,但在您的 else 中,您传递了 2。因此,它现在正在搜索 item.id == item.children,这可能总是错误的,它将继续运行您的功能。
  • 哦,你是对的,很抱歉忽略了这一点。感谢您的回答!
  • 没问题。有时只需要第二双眼睛:-)

标签: javascript jquery recursion javascript-namespaces


【解决方案1】:

我刚刚用更简单的变量名重写了您的代码:

var a = {
    b: = [{id: 1}, {id: 2}, {id: 3}]
};
a.get = function( searchId ) {
    var match = null;

    $.each(a.b, function(key, value) {
        if ( value.id === searchId ) {
            // Yes we found the match, break and everything

            match = value;
            return false;
        }
        else {
            match = a.get();

            if ( match ) {
                return false;
            }
        }
    });
    return match;
};

a.get(1) // will return {id: 1}
a.get(2) // will throw recursive error

为什么?

由于您的结构,您总是将$.each 指向a.b

因此它是这样的:

循环遍历a.b: a.b[0].id === searchId ?
好的,一切都很好,返回第一个值

如果不是 a.b[0].id === searchId
循环遍历a.b
a.b[0].id === searchId ?
好的,一切都很好返回第一个值
如果不是 a.b[0].id === searchId
循环遍历a.b
.....

希望你理解:

要解决这个问题,您需要指定我们必须循环的数组:

QuoteProductService.getQuoteProduct = function (quoteproductid, loopArray) {
    var founditem = null;

    // if (loopArray) {loopArray = loopArray} else { loopArray=Quote...QuteConfig.. }
    loopArray = loopArray || QuoteProductService.QuoteProductConfigurations;

    $.each(loopArray, function (index, item) {
        if(item.id == quoteproductid) {
            founditem = item;
            return false; // break the $.each if an item is found
        } else {
            founditem = QuoteProductService.getQuoteProduct(quoteproductid, item.children);
            if(founditem != null) return false; // break the $.each if an item is found
        }
    });
    return founditem;
}

【讨论】: