jquery / javascript错误 - 过多的递归 - 具有自我调用功能

时间:2013-07-08 13:41:36

标签: javascript jquery function recursion

我对一个从内部调用自身的函数有一个小问题。 以下功能非常有用,可以在这里看到......

http://jsfiddle.net/justinayles/frPZ8/2/

但是如果你点击一个正方形,然后点击后面的链接并来回几次,最终它会减速并最终因“过多的递归错误”而崩溃。我真的没有看到任何其他方式来实现我在这里尝试做的事情?我有点明白问题是什么,但是想知道是否还有其他方法可以做到这一点,也许重命名这个功能?我试图避免重复太多的代码。任何帮助表示感谢,谢谢。

var questionArray = [];         
var cardArray = [];

// extend array for IE !!
if (!Array.prototype.filter) {
    Array.prototype.filter = function(fun /*, thisp*/) {
        var len = this.length >>> 0;
        if (typeof fun != "function")
            throw new TypeError();

        var res = [];
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this) {
                var val = this[i]; // in case fun mutates this
                if (fun.call(thisp, val, i, this))
                    res.push(val);
            }
        }
        return res;
    };
}

function setupPage(whichpage, questionArray) {

    var html = "",
        backlink = "",
        activestep = "",
        undertext = "",
        qArray = questionArray;

    switch(whichpage) {
        case '1':

            var pg1 = questionArray.filter(function (el) {
                return el.page == "step1";
            });

            $.each(pg1, function(key,val) {
                html += '<a class="quest ' + val.star + '" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a>';
            }); 

            backlink = "0"; 
            activestep = "1";
            undertext = "";

            break;              
        case '2a':

            var pg2a = questionArray.filter(function (el) {
                return el.page == "step2a";
            });

            $.each(pg2a, function(key,val) {
                html += '<a class="quest ' + val.star + '" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a>';
            }); 

            backlink = "1";
            activestep = "2";
            undertext = "";

            break;
        case '2b':

            var pg2b = questionArray.filter(function (el) {
                return el.page == "step2b";
            }); 

            $.each(pg2b, function(key,val) {
                html += '<a class="quest ' + val.star + '" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a>';
            }); 

            backlink = "1";
            activestep = "2";
            undertext = "";

            break;
        case '3a':

            var pg3a = cardArray.filter(function (el) {
                return el.page == "3a";
            });

            $.each(pg3a, function(key,val) {
                html += '<div class="cardblock"><a class="wrapcard" href="' + val.path + '" target="' + val.target + '"><img border="0" alt="' + val.title + '" src="http://dummyimage.com/178x112/000/00ffd5.png"  alt="placeholder image" /></a>';
                html += '<a class="cardtitle" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a></div>';
            }); 

            backlink = "2a";
            activestep = "3";
            undertext = "Choose a programme";

            break;
        case '3b':

            var pg3b = cardArray.filter(function (el) {
                return el.page == "3b";
            }); 

            $.each(pg3b, function(key,val) {
                html += '<div class="cardblock"><a class="wrapcard" href="' + val.path + '" target="' + val.target + '"><img border="0" alt="' + val.title + '" src="http://dummyimage.com/178x112/000/00ffd5.png" /></a>';
                html += '<a class="cardtitle" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a></div>';
            }); 

            backlink = "2b";
            activestep = "3";
            undertext = "Choose a programme";

            break;                  
    }

    // make the dom changes..
    if ( backlink !== "0" ) {
        html += '<a id="backlink" href="' + backlink + '">&lt;&lt; back a step</a>';
    }

    $('.wrapdots span').removeClass('active');
    $('.wrapdots span.step'+activestep).addClass('active');

    $('p.underdots').html(undertext);

    $('#wrapper').fadeOut('fast', function() {
        $(this).html(html).fadeIn('fast');
    });

    $('#wrapper').on('click', '#backlink', function(e) {

        e = e || window.event;
        e.target = e.target || e.srcElement;

        var goto = e.target.href;
        goto = goto.split('/');
        goto = goto.pop();

        switch(goto) {
            case '1':
                e.preventDefault(); 
                setupPage('1', qArray);
                break;
            case '2a':
                e.preventDefault(); 
                setupPage('2a', qArray);
                break;
            case '2b':
                e.preventDefault(); 
                setupPage('2b', qArray);                        
                break;
            case '3a':
                e.preventDefault(); 
                setupPage('3a', qArray);
                break;
            case '3b':
                e.preventDefault(); 
                setupPage('3b', qArray);                        
                break;                      
        }

    });

    $('#wrapper').on('click', '.quest', function(e) {

        e = e || window.event;
        e.target = e.target || e.srcElement;

        var goto = e.target.href;
        goto = goto.split('/');
        goto = goto.pop();

        switch(goto) {
            case '1':
                e.preventDefault(); 
                setupPage('1', qArray);
                break;
            case '2a':
                e.preventDefault(); 
                setupPage('2a', qArray);
                break;
            case '2b':
                e.preventDefault(); 
                setupPage('2b', qArray);                        
                break;
            case '3a':
                e.preventDefault(); 
                setupPage('3a', qArray);
                break;
            case '3b':
                e.preventDefault(); 
                setupPage('3b', qArray);                        
                break;  
            default:
                e.preventDefault(); 
                break;
        }

    });

}

// doc ready...
$(function() {

    // do questions
    $('question').each(function() {
        var qobj = { 
            title : $(this).attr('qTitle'),
            star : $(this).attr('class'),
            path : $(this).attr('path'),
            page : $(this).attr('page'),                            
            target : $(this).attr('target')
        }
        questionArray.push(qobj);
    });

    // got the questions, lets now setup page 1 !!
    setupPage('1', questionArray);

    // do cards
    $('card').each(function() {
        var cobj = { 
            title : $(this).attr('cTitle'),
            path : $(this).attr('path'),
            img : $(this).attr('img'),                              
            page : $(this).attr('page'),                            
            target : $(this).attr('target')
        }
        cardArray.push(cobj);                           
    });     

});

1 个答案:

答案 0 :(得分:1)

这不是您想要使用递归的情况。每次点击都会将更多事件绑定到DOM,但永远不会释放它们。我建议您将$('#wrapper').on('click'...代码从setupPage功能中提取出来,使您的点击事件仅绑定一次。

递归函数最适用于扫描列表树的情况,在这种情况下,您不知道它们的深度。仅供参考,Code Academy有关于递归的部分,我发现它很有帮助。