JavaScript - 如何在递归期间重置局部变量?

JavaScript - How to reset a local variable during recursion?

有一个对象具有 "value" or/and "children" 作为属性。问题是将所有值和 return 相加。这是工作。我用过递归。我正在使用全局变量来存储总和。

请参考- https://jsfiddle.net/ws6ty78b/1/

function sumup(node) {
  sum+=node.value;
  if (node.children && node.children.length > 0) {
    for (var i =0; i < node.children.length; i++) {
        sumup(node.children[i]);
    }
}
return sum
}

问题 - 再次调用相同的函数时,我没有得到相同的结果。总和翻了一番。我知道为什么会这样,因为我使用的是全局变量。

问题 - 对于上述问题,有没有办法让我对任意次数的调用都得到相同的结果。

请注意限制-

1) 不要更改函数签名和声明。

2) 在'sumup'函数中使用'sum'变量。

3) 不要使用任何额外的变量。

4) 仅在 sumup 函数内进行更改。

为了实现您的目标,函数 sumup() 将被调用 N 次。我们不知道这个 N 是多少,因为它取决于子节点的递归次数。此外,由于限制,我们无法编辑函数签名,也无法在其他地方编写代码来做任何事情,甚至不能手动将 sum 设置为 0。

因此我们需要一种方法来区分一组调用和下一组调用,并重置它。

我的想法是我们设置一个阈值,使用closure。从第一次调用开始,在示例中,您有 5 秒的时间继续调用,之后它将重新开始。这真的是我们所能做的,除非提供另一种区分调用的方法。

编辑:我在这里尝试的是将所有递归保留为基本情况,而不更改对象。由于 OP 已经接受了该解决方案,我正在添加一个节点重置器 属性。如果任何节点的重置器未定义或为空、零或未定义,这将重置总和。我们必须假设它没有在启动对象中定义。正如我所说,这是一个薄弱的假设。通过在递归时定义它,结转当前总和。 为了最终的兴趣,我也会保留原来的时间门槛想法。

var obj = {
  "value": 4,
  "children": [
    {
      "value": 2,
      "children": [
        {
          "value": 1
        }
      ]
    },
    {
      "value": 9
    }
  ]
}


const sumup = (function(){
  var lastTime = 0;
  var newTime = 0;
  var sum = 0;
  const timeThreshold = 5000; // 5 seconds
  return function(node) {
    newTime = new Date().getTime();
    if(!node["resetter"] || (newTime-lastTime >= timeThreshold)){
      sum=0;
      lastTime = newTime;
      }
      sum+=node.value;
      if (node.children && node.children.length > 0) {
        for (var i =0; i < node.children.length; i++) {
          sumup(Object.assign({"resetter":true},node.children[i]));
        }
      }
      return sum;
   }
})();

console.log(sumup(obj)); //16
console.log(sumup(obj)); //32! should print 16 everytime

您可以 call 在递归时进行求和,并 assign/test 针对自定义 this:

var obj = {
  "value": 4,
  "children": [{
      "value": 2,
      "children": [{
        "value": 1
      }]
    },
    {
      "value": 9
    }
  ]
};
var sum = 0;

function sumup(node) {
  //Only make change within this function body
  if (!this || !this.recurse) sum = 0;
  sum += node.value;
  if (node.children && node.children.length > 0) {
    for (var i = 0; i < node.children.length; i++) {
      sumup.call({ recurse: true }, node.children[i]);
    }
  }
  return sum
}

console.log(sumup(obj));
console.log(sumup(obj));

或者,您可以完全取消全局变量,而是对子项使用递归 reduce

var obj = {
  "value": 4,
  "children": [{
      "value": 2,
      "children": [{
        "value": 1
      }]
    },
    {
      "value": 9
    }
  ]
};

const sumup = (node) => (
  node.value + (node.children
    ? node.children.reduce((a, child) => a + sumup(child), 0)
    : 0
  )
);

console.log(sumup(obj));
console.log(sumup(obj));

您可以简单地将每个子节点的值与当前节点的值相加:

function sumup(node) {
      sum=node.value;
      if (node.children && node.children.length > 0) {
        for (var i =0; i < node.children.length; i++) {
          sum+=sumup(node.children[i]);
        }
      }
      return sum
    }