【问题标题】:Javascript, map returns undefinedJavascript,地图返回未定义
【发布时间】:2018-05-15 01:06:43
【问题描述】:

所以我有 24 个“person”对象,它们是使用“names”数组创建的,因此“dude”名称会重复; 接下来,我创建了一个函数,将一些随机数与对象 id-s 进行比较,如果它们相等,那么我将尝试创建与该 id 匹配的人名的新数组。

(如果这听起来太复杂,我很抱歉,但我真的不明白为什么我的 ma​​p 方法 不起作用。)

这是我的代码的 2 个版本。 第一个有效,可以做我想做的事。

var names = ["jim", "jack", "aaron", "hugh", "jeff", "cameron", "allen", "charlie"];
var len = 3,
  arr1 = [],
  counter = 1;

for (var i = 0; i < len; i++) {
  names.forEach(name => {
    arr1.push({
      id: counter,
      dude: name
    });
    counter++;
  });
}

console.log(arr1);

function checkName(nums) {
  var namesarr = [];
  for (var i = 0; i < arr1.length; i++) {
    nums.forEach(function(num) {
      if (num === arr1[i].id) {
        namesarr.push(arr1[i].dude);
      }
    });
  }
  return (namesarr);
};

console.log(checkName([1, 3, 6]));

但是在第二个版本中,我的 map 函数返回 undefined, 我真的不明白为什么?!

var names = ["jim", "jack", "aaron", "hugh", "jeff", "cameron", "allen", "charlie"];
var len = 3,
  arr1 = [],
  counter = 1;


for (var i = 0; i < len; i++) {
  names.forEach(name => {
    arr1.push({
      id: counter,
      dude: name
    });
    counter++;
  });
}

console.log(arr1);

function checkName(nums) {
  var namesarr;
  for (var i = 0; i < arr1.length; i++) {
    namesarr = nums.map(function(num) {
      if (num === arr1[i].id) {
        return arr1[i].dude;
      }
    });
  }
  return (namesarr);
};
console.log(checkName([1, 3, 6]));

【问题讨论】:

  • 你的map 函数总是返回一些东西。如果您不在显式的return 语句中执行此操作,则返回值为undefined。换句话说:你不能使用map 来创建一个长度不同的数组*
  • namesarr.filter(a =&gt; a != null) 将摆脱未定义但通常不返回地图看起来很不确定。使用地图前的过滤器删除不需要的值。
  • 试试.map(your map code).filter(code to filter out undefined) 或其他方式:p
  • console.log( [1, 3, 6].map(i =&gt; names[i - 1]) );相比,这似乎有点过于复杂了

标签: javascript arrays object dictionary


【解决方案1】:

您将在循环的每次迭代中覆盖 namesarr 变量。我认为您的意思是在每次传递时都添加它,而不是覆盖它。为此,您可以使用数组.concat 方法。

然后,最后,确保在返回结果之前过滤掉结果中的所有 undefined 值。

var names = ["jim", "jack", "aaron", "hugh", "jeff", "cameron", "allen", "charlie"];
var len = 3,
  arr1 = [],
  counter = 1;


for (var i = 0; i < len; i++) {
  names.forEach(name => {
    arr1.push({
      id: counter,
      dude: name
    });
    counter++;
  });
}

console.log(arr1);

function checkName(nums) {
    var namesarr = [];
    for (var i = 0; i < arr1.length; i++) {
        namesarr = namesarr.concat(nums.map(function(num) {
            if(num === arr1[i].id) {
                return arr1[i].dude;
            }
        }));
    }
    return (namesarr.filter(Boolean));
};
console.log(checkName([1,3,6]));

【讨论】:

    【解决方案2】:

    map() 的结果是所有返回值的数组。如果函数不执行return语句,则相当于以return undefined结尾。

    在您的第二个版本中,每当if 条件失败时,您都不会执行return arr1[i].dude;,因此默认情况下它会返回undefined。就像你写的那样:

    namesarr = nums.map(function(num) {
      if (num === arr1[i].id) {
        return arr1[i].dude;
      } else {
        return undefined;
      }
    });
    

    两个版本的代码之间的另一个区别是,第二个版本每次通过for 循环重新分配namesarr。所以你只是打印最后一次迭代的结果。

    第一个版本在循环之前分配一次,并且仅在if 条件成功时添加,因此您可以从所有迭代中获取元素。

    【讨论】:

      【解决方案3】:

      您的map 函数不会为数组中的所有项目返回某些内容(因为if),因此结果数组中的某些值将是undefined

      另外,您的map 位于循环arr1 的循环中,因此对于该循环的每次迭代,数组namesarr 都会被覆盖。所以map 就好像它只应用于arr1 中的最后一个元素,因此如果nums 包含N 元素,那么namesarr 将至少有N - 1 undefined 值在其中( N - 1 如果arr1 的最后一个对象匹配nums,则N 如果不匹配。

      使用reduce而不是map可以更好地解决问题:

      function checkName(nums) {
          return arr1.reduce(function(namesarr, obj) {     // for each object obj in the array arr1
              if(nums.indexOf(obj.id) !== -1) {            // if the object's id is in the array nums
                  namesarr.push(obj.dude);                 // then add the object's dude to the array namesarr
              }
              return namesarr;
          }, []);                                          // the empty array to initialize namesarr
      }
      

      【讨论】:

        猜你喜欢
        • 2013-04-08
        • 1970-01-01
        • 1970-01-01
        • 2013-12-31
        • 1970-01-01
        • 2021-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多