简体   繁体   English

计算一个函数在JS中递归调用的次数

[英]Counting how many times a function has been called recursivly in JS

I have got a homework where i am supposed to write a pseudo random number generator in JavaScript. 我有一个作业,应该在JavaScript中编写一个伪随机数生成器。 This is the code bit i wrote 这是我写的代码位

var k = 0;

var slump = function(n, k) {
  if (k < 10) {
  console.log("stop");
  }
  else {
    k++;
    console.log((5*n + 1) % 8);
    return slump((5*n + 1) % 8, k);
  }
};

slump(0);

k is supposed to hold the amount of times the function has been called. k应该保留函数被调用的次数。 But instead of just running the function ten times, it just keeps running. 但是,它不会一直运行十次,而是会继续运行。 Is there any way to get around this? 有什么办法可以解决这个问题?

You have two subtly different options here, depending on how idiomatic and clever you'd like to get. 根据您想获得的惯用和聪明程度,这里有两个细微不同的选项。

The classic implementation, with a slight tweak as JS doesn't support default parameters, would be to use something like: 由于JS不支持默认参数,因此需要稍作调整的经典实现将使用以下方法:

var finalDepth = 0;
function slump(n, k) {
    k = k || 0; // Set to 0 if falsy (null, undef, or 0)
    if (logic) {
        finalDepth = k; // Record the depth on the last call
    } else {
        return slump((5*n + 1) % 8, k + 1);
    }
}

This will very simply record the deepest the stack has been, and hang onto the value until the next call. 这将非常简单地记录堆栈最深的位置,并将其挂起,直到下一次调用为止。

If you want to be slightly more JS-like, you can use closure to keep track of the calls: 如果您想更像JS,可以使用闭包来跟踪调用:

function createGenerator() {
  var counter = 0;
  return {
    slump: function (n) {
      ++counter; // Closure captures counter, counter persists between slump calls but is unique for each createGenerator
      if (logic) {
        // stop
      } else {
        return slump((5*n + 1) % 8, k + 1);
      }
    },
    getCounter: function () { return counter; }
  }
}

You may be able to use some of the features from ES6 iterators (or generators) to make this more clever. 您也许可以使用ES6迭代器 (或生成器)的某些功能来使其更加巧妙。

Whenever you write a recursive function, you need to make sure that: 每当编写递归函数时,都需要确保:

  1. There's a base case (in your case, when the console.log statement runs) 有一个基本情况(在您的情况下,当console.log语句运行时)
  2. The function proceeds towards the base case, and 函数朝基本情况前进,并且
  3. The function works, assuming the success of the recursive call. 假定递归调用成功,该函数将起作用。

You're running into a problem with the second part; 您在第二部分遇到问题; you increment k, but that doesn't bring you any closer to the part where k < 10 . 您增加k,但是并不能使您更接近k < 10的部分。 In short, you probably want to switch that test around and make sure you're initially calling the function with the right number of arguments. 简而言之,您可能希望切换该测试,并确保最初使用正确数量的参数调用该函数。 (Aadit M Shah pointed out that you're calling it with one, and it expects two, meaning that it ends up undefined when you call it.) (Aadit M Shah 指出您正在用一个来调用它,并且期望它是两个,这意味着当您调用它时它最终未定义。)

Either way, iteration would definitely work better here: 无论哪种方式,迭代在这里肯定会更好地工作:

var n = 0;
for(var i = 0; i < 10; i++) {
    n = (5 * n + 1) % 8;
    console.log(n);
}

The function parameter k is uninitialized, therefore not a number. 功能参数k未初始化,因此不是数字。 this means in particular that the termination test k < 10 fails as well as the k++ statement doesn't change k ' s value. 这尤其意味着终止测试k < 10失败,并且k++语句不会更改k的值。 so slump gets always called with the same value for parameter k and the recursion never stops. 因此,总是以相同的参数k值调用坍落度,并且递归永远不会停止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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