为什么我要使用NaN来处理这个数组?

时间:2015-03-06 20:07:49

标签: javascript arrays

我正在尝试使用Book Eloquent Javascript来改进我的JS。我正在研究question 5.2的解决方案,并希望对它为什么出错以及返回NaN进行一些探索。我的解决方案是:

function average(array) {
  function plus(a, b) { return a + b; }
  return array.reduce(plus) / array.length;
}

var byName = {};
ancestry.forEach(function(person) {
  byName[person.name] = person;
});

var knownMothers = ancestry.filter(function(person){
  return person.mother != null;
});

var ageDifferences = knownMothers.map(function(person){
  return person.born - [person.mother].born

});

console.log(knownMothers);
console.log(ageDifferences);
console.log(average(ageDifferences));

最后两个console.log statemets返回NaN。

ancestry是一个格式如下的数组:

[0: {
    name:   "Carolus Haverbeke"
    sex:    "m"
    born:   1832
    died:   1905
    father: "Carel Haverbeke"
    mother: "Maria van Brussel"
}
1:  {
    name:   "Emma de Milliano"
    sex:    "f"
    born:   1876
    died:   1956
    father: "Petrus de Milliano"
    mother: "Sophia van Damme"
}]

解决方法是将此练习位于上面的链接中。它在代码中使用了byName对象,因此绕过了在输出中获取NaN。有人可以澄清为什么我需要在byName对象中返回元素吗?我知道它缺失的部分,但不知道为什么,真的想要理解。谢谢!

我复制了下面的答案(我不太了解)以供参考:

var differences = ancestry.filter(function(person) {
  return byName[person.mother] != null;
}).map(function(person) {
  return person.born - byName[person.mother].born;
});

console.log(average(differences));

3 个答案:

答案 0 :(得分:0)

我认为您对ageDifferences的定义缺少对byName的引用。 (以及防范byName[person.mother]未设置的安全措施。)

答案 1 :(得分:0)

问题出在这里,

return person.born - [person.mother].born

person.born是一个数字& [person.mother]应该是数组(因为[])(根据你的定义)。和[person.mother] .born也应该是一个数字(根据要求)。所以,你不能使用[person.mother] .born,你应该找到#34; person.mother"键入你的对象。

当你这样做时,

console.log(average(ageDifferences));

方法'平均'用于将数组作为参数。

因为,ageDifferences没有数字作为元素,它给出了NaN错误。

答案 2 :(得分:0)

WORKING DEMO

NaN的原因是你试图减去person.born - person.mother.born,其中第二个操作数甚至没有退出。所以它的数字 - 未定义。所以你得到了NaN。

对于knownMothers,你将它等同于null,这可能与所有条件都不匹配。您还需要更新knownMothers过滤器。你需要检查这个人是否有一个母亲以及母姓是否存在于byName对象中。如下所示:

var knownMothers = ancestry.filter(function(person){
          return person.mother && byName[person.mother];
        });

一旦你这样做,你就能获得ageDifference和平均值。

   var ancestry = [{
        name:   "Carolus Haverbeke",
        sex:    "m",
        born:   1832,
        died:   1905,
        father: "Carel Haverbeke",
        mother: "Maria van Brussel"
    },  {
        name:   "Emma de Milliano",
        sex:    "f",
        born:   1876,
        died:   1956,
        father: "Petrus de Milliano"
    }, {
      name : "Maria van Brussel",
      sex:    "m",
        born:   1782,
        died:   1905,
        father: "Carel Haverbeke",
        mother: "Maria van"
    }];
    function average(array) {
      function plus(a, b) { return a + b; }
      return array.reduce(plus) / array.length;
    }

    var byName = {};
    ancestry.forEach(function(person) {
      byName[person.name] = person;
    });
    var knownMothers = ancestry.filter(function(person){
      return person.mother && byName[person.mother];
    });
    var ageDifferences = knownMothers.map(function(person){
      return person.born - byName[person.mother].born;
      // assumption: you are trying to get mother's born year from the byName object
    });

    console.log(knownMothers);
    console.log(ageDifferences);
    console.log(average(ageDifferences));