开发者问题收集

JavaScript 最大调用堆栈

2015-08-13
66

大家好,我为我的音乐播放列表创建了两个函数,

  • 一个转到下一首音乐
  • 一个转到随机音乐

我知道我的代码不够干净和实用,但它运行得相当好,

在我的示例中,只有当我单击下一个直到最后一个音乐 6次 时才会出现错误,但是当我单击随机时,出现错误 Uncaught RangeError:超出最大调用堆栈大小 ,不知道为什么,这是我的代码:

测试

var array = {
   0: {
    "id" : 1,
       "nom" : "Musique 1",
       "durée" : "3m34"
   },
   1: {
    "id" : 2,
       "nom" : "Musique 2",
       "durée" : "2m32"
   },
   2: {
        "id" : 3,
       "nom" : "Musique 3",
          "durée" : "3m54"
   },
   3: {
    "id" : 4,
       "nom" : "Musique 4",
       "durée" : "2m19"
   },
   4: {
    "id" : 5,
       "nom" : "Musique 5",
       "durée" : "2m24"
   },
   5: {
    "id" : 6,
       "nom" : "Musique 6",
       "durée" : "1m58"
   }
};
var count = getObjectLength(array), itmsl = [], mus = -1;

function aleatoire(p){
      var item = Math.floor(Math.random()*count);
      mus = item;
      if(itmsl.indexOf(item) < 0){
        itmsl.push(item);
        echo(array[item]);             
      }else{
        aleatoire();               
      }
      if(itmsl.length >= count){
        itmsl = [];
      }
}
function suivant(){
    mus++;
    if(itmsl.indexOf(mus) < 0 && typeof array[mus] !== 'undefined'){
      itmsl.push(mus);
      echo(array[mus]);
    }else{
      mus = -1;
      itmsl = [];
      suivant();
    }
}
function echo(str){
    if(typeof str != "undefined"){
        console.log(str);
    }else console.log('error');
}

function getObjectLength(obj){
    var length = 0;
    for ( var p in obj ){
      if ( obj.hasOwnProperty( p ) ){
        length++;
      }
    }
  return length;
}

谢谢您的帮助

2个回答

函数 suivant() 既不接受参数也不返回值。因此,在我看来,它是无用的递归(递归的整个要点是使用调用堆栈来管理数据存储,但您似乎已经使用数组手动管理它)。它以这种方式编写的唯一原因似乎是为了模拟 goto

因此,将其更改为 while 循环(这当然只是 goto 的另一种形式)非常简单:

function suivant(){
    var end = 0;

    while (!end) {
        mus++;
        if(itmsl.indexOf(mus) < 0 && typeof array[mus] !== 'undefined'){
            end = 1;
            itmsl.push(mus);
            echo(array[mus]);
        }else{
            mus = -1;
            itmsl = [];
        }
    }
}

类似地,函数 aleatoire 也应该是迭代的:

function aleatoire(){
    var end = 0;

    while (!end) {
        var item = Math.floor(Math.random()*count);
        mus = item;
        if(itmsl.indexOf(item) < 0){
            end = 1;
            itmsl.push(item);
            echo(array[item]);             
        } else {
            // don't end
        }
        if(itmsl.length >= count){
            itmsl = [];
        }
    }
}
slebetman
2015-08-13

如果将递归断路器移至顶部,它应该可以工作。在您的随机方法中将此代码移至顶部。一旦这样做,您实际上根本不需要递归,并且可以安全地注释掉 else

 function aleatoire(){
          if(itmsl.length >= count){
            itmsl = [];
          }
          var item = Math.floor(Math.random()*count);
          mus = item;
          if(itmsl.indexOf(item) < 0){
            itmsl.push(item);
            echo(array[item]);             
          }
//else{
       //     aleatoire();               
        //  }

    }

同样的方法也可以应用于后续方法。

jozzy
2015-08-13