2013-04-03 59 views
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 

我不明白为什么第二个窗体不起作用。欢迎任何解释。JavaScript Map Reduce:怪异行为

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

+0

这是“在浏览器中”,我更新了我的答案。 – AsTeR 2013-04-03 22:07:13

+0

@AsTeR:具体而言,尚未广泛实施的[ES5'reduce'](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.21)。 – 2013-04-03 22:09:58

回答

6

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

减少饲料像indexarray值来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]] 

由于数组[6]是不是一个号码,结果是NaN


下面是从MDN一个非常类似的例子:

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

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

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

+0

对于downvoter,谨慎解释为什么? – 2013-04-03 22:10:22

3

reduce的回调被称为传递四个参数:previousValuecurrentValueindexarray。而且由于Math.minvariadic功能,您的代码:

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)); 

会的作品。