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

放肆的年华 提交于 2020-01-06 04:01:20

问题


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

});

回答1:


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.



来源:https://stackoverflow.com/questions/17528183/jquery-javascript-error-too-much-recursion-with-self-calling-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!