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 reduce http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.21
答案 0 :(得分:6)
Math.min
接受多个参数。这与parseInt
或其他类似函数不起作用的原因完全相同。你需要自己绑定参数。
将index
和array
等值添加到Math.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忽略,但不是第二个参数,因此可能会产生混淆。
答案 1 :(得分:3)
reduce的回调被称为传递四个参数:previousValue
,currentValue
,index
和array
。由于Math.min是variadic函数,因此您的代码为:
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
不是数字。
你也可以像high-ordered function这样解决这类问题:
function binary (fn) {
return function (a, b) {
return fn.call(this, a, b);
}
}
然后:
t.map(Math.abs).reduce(binary(Math.min));
会有效。