简体   繁体   中英

jquery/javascript error - too much recursion - with self-calling function

I have a small problem with a function that calls itself from within itself. The following function pretty much works, as can be seen here ...

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

but if you click a square and after that click the back link and go back and forth a few times, eventually it will slow down and ultimately crash with a 'too much recursion error'. I cant really see any other way to achieve what I am trying to do here ? I kind of understand what the problem is, but was wondering if there was another way to do this, maybe rename the function? im trying to avoid duplication too much code. any help appreciated, thanks.

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);                           
    });     

});

This isn't a case you'd want to use recursion. Every click binds more events to the DOM but never releases them. I'd recommend pulling your $('#wrapper').on('click'... code out of your setupPage function that way your click events are only bound once.

Recursive functions are best used for situations like scanning list trees where you don't know how deep they go. FYI, Code Academy has section on recursion that I found helpful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM