曾-..曾曾示例 - 雄辩的 JS
Great-great-great-great-... Example - Eloquent JS
我正在为"曾曾-...曾示例来自 Eloquent JS 中的高阶函数章节。我不明白其中一个函数如何从仅包含祖先数据的对象创建值。以下是功能:
function reduceAncestors(person, f, defaultValue) {
function valueFor(person) {
if (person == null)
return defaultValue;
else
return f(person, valueFor(byName[person.mother]),
valueFor(byName[person.father]));
}
return valueFor(person);
}
和
function sharedDNA(person, fromMother, fromFather) {
if (person.name == "Pauwels van Haverbeke")
return 1;
else
return (fromMother + fromFather) / 2;
}
我不明白valueFor(byName[person.mother](如何从这样的对象生成数值:
"Carolus Haverbeke" : {
"name": "Carolus Haverbeke",
"sex": "m",
"born": 1832,
"died": 1905,
"father": "Carel Haverbeke",
"mother": "Maria van Brussel"}
在声明 sharedDNA
之后,您将看到:
var ph = byName["Philibert Haverbeke"];
console.log(reduceAncestors(ph, sharedDNA, 0) / 4);
byName
是一个充满键:值对的对象,就像你为 Carolus 编写的那样。键是人的名字,对应的值是"人对象",它具有键:值对,分别是"姓名"、"母亲"、"父亲"等。这很有用,因为对于每个递归循环,我们需要找出母亲和父亲的结果,因此我们可以轻松地查找当前人的母亲和父亲的名字,然后从 byName 对象访问他们的 person 对象。所以排队
var ph = byName["Philibert Haverbeke"];
我们为菲利伯特提取这个 Person 对象并将其存储在一个名为 ph
的变量中。然后,使用此 person 对象、sharedDNA
函数和0
defaultValue
调用reduceAncestors
(稍后会详细介绍(。我们除以 4,因为菲利伯特是作者的祖父。所以,这个函数会返回祖父和伟大、伟大、伟大、伟大......爷爷。为了找到作者的共同DNA,我们需要将他祖父的结果除以4(每一代将共享DNA减半(。
为了更容易理解这个例子,我发现尝试找到一些更简单的例子的sharedDNA很有帮助。首先,让我们试着找到Pauwels van Haverbeke的共同DNA,伟大的,伟大的,伟大的,伟大的......祖父我们首先用来比较。所以我们知道答案:鲍威尔斯分享了他自己100%的DNA。
因此,在本例中,将使用 Pauwers 的 person 对象、sharedDNA
函数和使用以下代码0
defaultValue
调用reduceAncestors
:
var pauwels = byName["Pauwels van Haverbeke"];
console.log(reduceAncestors(ph, sharedDNA, 0));
在reduceAncestors
中,我们将进入 else 子句和
return f(person, valueFor(byName[person.mother]), valueFor(byName[person.father]));
将成为
return sharedDNA(pauwels, valueFor(null), valueFor(null));
person.mother
和person.father
表达式的计算结果为 null
,因为 Pauwels的母亲和父亲不在数据集中。 sharedDNA
想要调用,但需要等待两个valueFor(null)
调用进行评估。
当valueFor
被null
调用时,它会进入if
子句,因为person === null
为真。然后,它将return defaultValue
,您还记得,我们在最初的reduceAncestors
调用中0
传入。
所以,现在上面的一行变成了
return sharedDNA(pauwels, 0, 0)
如果我们查看 sharedDNA
函数,我们会看到我们将计算第一个if
子句,因为person.name == "Pauwels van Haverbeke"
为真。因此,我们将返回 1。这样,并使用最简单的示例,您可以看到sharedDNA
如何返回数字。
现在,让我们再举一个例子,这次是Pauwel的孩子Lieven van Haverbeke。我们将这样称呼它:
var pauwelsChild = byName["Lieven van Haverbeke"];
console.log(reduceAncestors(pauwelsChild, sharedDNA, 0));
在reduceAncestors
中,我们将进入else
条款,我们将得到:
return sharedDNA(pauwelsChild, valueFor(byName["Lievijne Jans"]), valueFor(byName["Pauwels van Haverbeke"]));
我们已经知道valueFor(byName["Pauwels van Haverbeke"])
返回 1。对于另一个论点,我们有valueFor(byName["Lievijne Jans"])
.这最终会sharedDNA({Lievijne's: object}, valueFor(null), valueFor(null));
因为Lievijne的父母都不在数据集中。这将评估为 sharedDNA({Lievijne's: object}, 0, 0);
.
进入sharedDNA
,我们看到它会return (fromMother + fromFather) / 2;
,在这种情况下将是return (0 + 0) / 2;
,或0
。所以,最后,我们回到
return sharedDNA(pauwelsChild, valueFor(byName["Lievijne Jans"]), valueFor(byName["Pauwels van Haverbeke"]));
我们现在有
return sharedDNA(pauwelsChild, 0, 1);
我们进入共享DNA,我们将评估语句return (0 + 1) / 2;
,这将返回0.5
。这是有道理的,因为Pauwel的孩子将共享他1/2的DNA。
基本上,sharedDNA
等待valueFor
的电话,让母亲和父亲回来。但请记住,valueFor
调用sharedDNA
因为这是我们传入的函数。因此,从本质上讲,sharedDNA
等待自己评估每个父母,而父母又需要评估每个父母。这将创建一个调用树,直到它命中 null(不在数据集中的族成员(并返回 0
,或者它命中 Pauwels,并返回 1
。然后,返回0
或1
,并且它来自的sharedDNA
调用将进行评估。当最外层的树"分支"开始返回0
或1
时,它们组合在一起(并除以2(。因此,来自鲍威尔斯的1
不断被稀释 1/2。因此,您的数字越来越小。
我希望这有帮助!我写了一个更详尽的解释,向您展示如何使用 Chrome 控制台来测试代码并添加console.log
语句来帮助您理解递归流程。
如果你看一下 sharedDNA
的函数声明,你会看到以下内容:
var ph = byName["Philibert Haverbeke"];
console.log(reduceAncestors(ph, sharedDNA, 0) / 4);
如果将其追溯到 reduceAncestors
,参数映射到:
person -> { name: "Philibert Haverbeke", ... },
f -> sharedDNA,
defaultValue -> 0
现在,看看valueFor()
.它总是返回一个数字,要么是defaultValue
,要么是sharedDNA
的结果,总是返回一个数字。 这是关键:如果一个人没有父母,那么使用defaultValue
,否则,它会在给定的关系之间产生共享DNA的比例,或者第三种情况,"1",如果这个人碰巧被命名为"Pauels van Haverbeke"。
回答您的问题,"如何为(...从 Person 对象生成一个数值",它只是返回sharedDNA
递归生成的值。
- 可以't让我的if语句处理js中的html表单输入
- 使用agility.js进行页面布局和合成
- 使用Clipboard.js复制span文本
- 使用JS如何动态更改显示的html文件中的文本背景颜色
- 强制模板刷新ember.js
- 如何编写HTML输入的JS内联
- Angular JS IE9 Hashbang url rewriting
- 使用JS将数组转换为json对象
- Node.js v6.2.0类扩展不是函数错误
- 当js函数's已执行
- 要求未定义JS回调参数
- 在自定义mean.io包中使用angular-chart.js作为依赖项
- 无法在数据endVal中设置值=“”;{{ucount}}”;使用Angular JS的CountUp
- 如何从Java/scala调用js美化程序
- sails js,如主页上所示的示例代码
- 如何使用 HTML 或 CSS 或 JS 重叠两个图像并在两者之间划一条交叉线,如以下示例所示
- 曾-..曾曾示例 - 雄辩的 JS
- jquery获取曾曾曾祖父母的ID
- PHP返回的代码没有出现,但它过去曾出现过
- 在Drupal 7中没有调用Javascript函数,而Drupal 7曾在Drupal 6中正常运行