3
var t = [-12, 57, 22, 12, -120, -3];

t.map(Math.abs).reduce(function(current, previousResult) {
    return Math.min(current, previousResult);
}); // returns 3

t.map(Math.abs).reduce(Math.min); // returns NaN

我不明白为什么第二种形式不起作用。欢迎任何解释。

编辑:技术背景:Chrome 和 Firefox JavaScript 引擎。见 ES5 减少http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.21

4

2 回答 2

6

Math.min接受多个参数。这与 this 不适用于parseInt或其他类似功能的原因完全相同。您需要自己绑定参数。

减少提供值,例如indexarrayMath.min

如果我们遵循以下步骤,我们可以确认这一点:

首先,我们代理 Math.min:

var oldMath = Math.min;
Math.min = function (){
   console.log(arguments)
   return oldMath.apply(Math, arguments);
}

然后我们运行第二个版本:

[-12, 57, 22, 12, -120, -3].reduce(Math.min);

哪些日志:

[-12, 57, 1, Array[6]]

由于 Array[6] 不是数字,因此结果为 NaN


这是来自 MDN 的一个非常相似的示例:

["1", "2", "3"].map(parseInt);

虽然可以预期 [1, 2, 3] 实际结果是 [1, NaN, NaN]

parseInt通常与一个参数一起使用,但需要两个。第二个是基数 对于回调函数,Array.prototype.map 传递 3 个参数:元素、索引、数组。 parseInt 忽略第三个参数,但不会忽略第二个,因此可能会造成混淆。

于 2013-04-03T22:04:22.130 回答
3

reduce的回调被称为传递四个参数: previousValuecurrentValue和. 因为Math.min是一个可变参数函数,所以您的代码:indexarray

t.map(Math.abs).reduce(Math.min); // returns NaN

相当于:

t.map(Math.abs).reduce(function(current, previousResult, index, array) {
  return Math.min(current, previousResult, index, array);
});

这就是为什么结果是NaN: 最后一个参数 ,array不是数字。

您还可以使用像这样的高阶函数来解决此类问题:

function binary (fn) {
  return function (a, b) {
     return fn.call(this, a, b);
  }
}

进而:

t.map(Math.abs).reduce(binary(Math.min));

将起作用。

于 2013-04-03T22:08:45.453 回答