函数式 JS - forEach 函数不起作用

Functional JS - forEach function not working

我正在尝试练习函数式编程,我开始使用 forEach 并减少给定数组中的零计数(eloquent JavaScript 第 5 章中的问题)。但我不明白为什么我的代码在某些情况下有效,但在其他情况下却无效。

下面的代码不起作用,遗漏 else 语句似乎是问题所在。但是为什么这里需要 else 语句而不是在某些情况下我 post 接近 post?

function forEach(arr, action) {
 for(var i = 0; i < arr.length; i++) {
   action(arr[i]);
  }
}

function reduce(cb, start, array) {
  forEach(array, function(el) { start = cb(start, el); });
 return start;
}

function countZeroes(array) {
  function counter(total, element) {
    if(element === 0) return total + 1; //excluding else statement seems to be the issue but why?
  }
  return reduce(counter, 0, array);
}
console.log(countZeroes([0,1,0,2,0,3, 0,4,2,0])); //returns NaN

如果我用 else 语句重写函数,它就可以工作:

function forEach(arr, action) {
  for (var i = 0; i < arr.length; i++) {
    action(arr[i]);
  }
}

function reduce(cb, start, array) {
  forEach(array, function(el) {
    start = cb(start, el);
  });
  return start;
}

function countZeroes(arr) {
  function counter(total, element) {
    if (element === 0) {
      return total + 1;
    } else {
      return total;
    }
  }
  return reduce(counter, 0, arr);
}

console.log(countZeroes([0, 1, 2, 0]));

但是,在下面的例子中代码不需要else语句,为什么?

function countTarget(arr, target) {
 var counter = 0;
  for(var i = 0; i < arr.length; i++) {
    if(arr[i] === target) counter++;  //no else statement required here
  }
  return counter;
}
console.log(countTarget([0,1, 0, 0, 2, 3, 0, 3, 0, 0, 0], 0));

function forEach(arr, action) {
 for(var i = 0; i < arr.length; i++) {
   action(arr[i]);
  }
}

function test(a) {
  return a === 0;
}

function countTarget(arr, target) {
  var counter = 0;
  forEach(arr, function(el) {
    if (test(el)) counter++;
  });
  return counter;
}
console.log(countTarget([1, 2, 3, 0, 3, 0], 0));

我将不胜感激。

function counter(total, element) {
    if(element === 0) return total + 1; //excluding else statement seems to be the issue but why?
}

在此函数中,当 element 为 0 时,您正在 return 计算某个值 (total + 1)。因此对于其他所有情况,此函数 return 未定义因为您没有为 else 大小写指定任何值。

undefined + number = NaN

您可以像这样检查 counter 的 returned 值

forEach(array, function(el) {
    console.log(start);
    start = cb(start, el); 
});

情况 1:没有别的

console.log(countZeroes([0,1,0,2,0,3, 0,4,2,0]));

记录值 0 1 undefined NaN 等等

情况 2:使用 else

console.log(countZeroes([0,1,0,2,0,3, 0,4,2,0]));

记录值 0 1 1 2 2 3 等等

编辑

当你定义如下函数时

function f_name() {
    // calculations
    return some_value;
}

javascript 将其实现为

function f_name() {
    // calculations
    return some_value;
    return undefined; // implied by javascript
}

a function 可以有多个 return 语句和函数 returns 当它在执行流程中遇到 return 并且剩余的代码变得无法访问时。

所以,在你的情况下

function counter(total, element) {
    if(element === 0) return total + 1; //excluding else statement seems to be the issue but why?
    return undefined; // implied
}

element 值为 0 时,函数 return total + 1 和剩余的代码 (return undefined;) 变得无法访问,但是当 element不是0,函数执行return undefined.

希望这能澄清您的疑问。

从您的 counter 函数中得到 return 的任何内容都会传递给对 counter 的下一次调用。因此,你需要 return something 你的计数器功能。如果不满足条件,return 未受影响的总数:

function counter(total, element) {
   return (element === 0) ? total + 1 : total;
}

解释: 您的 counter 函数根据某些逻辑递增 "total" 值,并且 return 是递增的值。然后 returned 值再次传递给 counter 函数。您的计数器函数的代码路径没有 return 值(当 if 语句未通过时)。在这种情况下,您没有 returning 任何东西...这类似于 returning undefined。如果你要隔离它,它看起来有点像这样:

// Let's say your current "total" count is 15
var total = counter(15, 2);
console.log(total); //-> undefined

因为 2 !== 0 - 条件没有通过,函数的结果是 undefined。现在,下次调用计数器时,它将如下所示:

var total = counter(undefined, 0);

由于 0 === 0,条件将通过,它会尝试增加总数...即 undefined:

return undefined + 1; //-> NaN

希望对您有所帮助。