2013-04-03 94 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)); 

會的作品。