首页 > 解决方案 > 如何使用递归更新局部范围的变量

问题描述

如果这是一个过于笼统的问题,请原谅我,但是当我需要开发递归算法来更新每个递归调用的一些值时,我似乎经常遇到这个问题。请看下面这个例子:

我想制作一个递归算法来累积给定配置文件的年龄以及该配置文件中存在的所有孩子和孩子的孩子等。

型材结构:

const profile = {
  name: 'peter',
  age: 56,
  kids: [{
    name: 'jill',
    age: 23,
    kids: [{
      name: 'jeter',
      age: 1
    }, {
      name: 'bill',
      age: 2
    }]
  }]
}

如果我在函数范围之外声明一个变量并更新它的工作原理。像这样:

let totalage = 0
function getAge(profile) {
  totalage = profile.age + totalage
  if(!profile.kids) return
  for(const kid of profile.kids) {
    getAge(kid)
  }
}
getAge( profile)
console.log(totalage)

按照这个逻辑,为了使函数更可重用,我想创建一个 shell 函数来设置年龄变量,这样就不必在任何时候全局声明我想要获取所有年龄,但是这个解决方案返回 0,原始年龄值:

function getAges(profile) {
  let age = 0
  recurs( profile, age)
  return age
}

function recurs(profile, age) {
  age = profile.age + age
  if(!profile.kids) return
  for(const kid of profile.kids) {
    recurs(kid, age)
  }
}
console.log(getAges(profile))

知道有什么问题吗?

标签: javascriptrecursion

解决方案


我想创建一个设置 age 变量的 shell 函数,这样当我想获得所有年龄时就不必全局声明它。知道有什么问题吗?

您需要在recurse内部声明函数getAges,以便它可以age通过闭包访问变量。请注意,JS 对于函数调用只有按值传递语义,因此当您将变量 ( age) 作为参数传递给函数时,分配给参数 ( age) 只会更新函数内部的局部变量。

function getAges(profile) {
  let age = 0
  function recurs(profile, age) {
    age += profile.age
    if (!profile.kids) return
    for (const kid of profile.kids)
      recurse(kid)
  }
  recurse(profile)
  return age
}

console.log(getAges(profile))

但正如其他答案所提到的,递归利用返回值要好得多,就像在@Nick 或@ippi 的片段中一样。


推荐阅读