雄辩的Javascript书第5章关于递归和祖先的示例

雄辩的Javascript书第5章关于递归和祖先的示例,javascript,recursion,Javascript,Recursion,翻阅这本书时,我发现了这段关于总结祖先的代码。有几个电路板已经讨论了这一部分的不同部分,但我遇到的问题是这一块: var thisOneCounts = current != person && test ( current ); 具体来说,什么时候current从不==对person?我似乎找不到一种情况,因为current总是被称为person。但很明显,我遗漏了一些东西,因为当我把代码取出时,它会返回一个不同的解决方案。下面是代码总数 function reduceA

翻阅这本书时,我发现了这段关于总结祖先的代码。有几个电路板已经讨论了这一部分的不同部分,但我遇到的问题是这一块:

var thisOneCounts = current != person && test ( current ); 
具体来说,什么时候current从不==对person?我似乎找不到一种情况,因为current总是被称为person。但很明显,我遗漏了一些东西,因为当我把代码取出时,它会返回一个不同的解决方案。下面是代码总数

 function reduceAncestors(person, f, defaultVal) {
     function valueFor(person) {
         if (person == null)
             return defaultVal;
         else
             return f(person, valueFor(byName[person.mother]), valueFor(byName[person.father]));
     }
     return valueFor(person);

 }

 function countAncestors(person, test) {
     function combine(current, fromMother, fromFather) {
         var thisOneCounts = current != person && test(current); // **
         return fromMother + fromFather + (thisOneCounts ? 1 : 0);
     }
     return reduceAncestors(person, combine, 0);
 }

 function longLivingPercentage(person) {
     var all = countAncestors(person, function (person) {
         return true;
     });

     var longLiving = countAncestors(person, function (person) {
         return (person.died - person.born) >= 70;
     });
     return longLiving / all;
 }
 console.log(longLivingPercentage(byName["Emile Haverbeke"]));

请注意,
reduceAncestors()
中的
valueFor()
函数是由原始用户的父母递归调用的,然后是祖父母等。这些递归调用可能会调用
f()
,而
f()
是来自
count祖先()
combine()
函数

因此,首先将起始人员传递给
reduceAncestors()
。它调用
f()
(即
combine()
内部函数)以及与父函数调用
valueFor()
的结果。这反过来将导致母亲被传递到
f()
,父亲被传递到
f()
。回到原始调用
count祖先()
的上下文中,
person
仍然是原始person,但是传递给
combine()
current
值将不同(它将是母亲或父亲或外祖母/祖父或外祖母/祖父等)

让我们看一下
longLivingPercentage()
函数中对
count祖先()
的第一个调用。我们传入起始人员和始终返回
true
的虚拟
test()
。我不知道代码期望系谱数据结构是什么,但我们假设它是这样的:

{
  person: "Bob",
  mother: {
    person: "Mary",
    mother: null,
    father: null
  },
  father: {
    person: "Jim",
    mother: null,
    father: null
  }
}
因此:

  • 为Bob调用了
    count祖先()
    函数
  • 它将Bob传递给
    reduceAncestors()
    ,以及对该
    combine()
    函数的引用
  • reduceAncestors()
    中,为Bob调用了
    valueFor()
    ,由于Bob不是null,我们可以调用
    f()
    ——它是
    combine()
    ——需要传递Bob、母亲和父亲
  • 然而,在调用
    f()
    之前,我们需要与母亲和父亲一起调用
    valueFor()
    ,因为这些调用的结果需要传递到
    f()
  • 因此母函数调用了
    valueFor()
    。它还想调用
    f()
    ,还需要检查母亲和父亲(即,鲍勃的母亲和鲍勃的母亲的父亲)
  • 这两个祖父母调用失败很快,因为它们为null,因此可以继续为Bob的母亲调用
    f()
  • 现在我们进入了
    combine()
    ,第一个参数-
    current
    -是Bob的母亲。
    combine()
    函数实例的上下文来自于当
    person
    是Bob时进行的函数调用,而Bob肯定不是他自己的母亲

  • 嗯,只有一种情况是当前的
    等于
    。Wich是通过
    longLivingPercentage(别名[“Emile Haverbeke”)
    的原始人。其他时候,当前的
    是埃米尔·哈弗贝克的祖先。因为
    person
    是Emile Haverbeke,所以除了Emile Haverbeke之外,
    person
    一直不是
    current


    我认为这个代码(current!=person)的目的是从计数结果中除去原始的person。在书中,作者没有添加
    current!=人

    谢谢你,尖头!我现在明白了。电流!=后续递归调用中的person,因为current将持续更改,而person将保持初始调用中的person。极大的帮助和超快速的响应。万分感谢!我整天都在为这个绞尽脑汁。