2014-06-12 193 views
2

我試圖壓平已在它的兩個對象的對象,所以我做了以下內容:爲什麼underscore.reduce在這兩種情況下的行爲不同?

var underscore = require('underscore'); 
var obj = { a: {x:1}, b: {y:2}}; 
underscore.reduce(obj, underscore.extend, {}); 

沒想到,我已經得到了輸出:

{ 
    '0': 'b', 
    x: 1, 
    a: { x: 1 }, 
    b: { y: 2 }, 
    y: 2 
} 

於是我已經試過在一個函數來包裝extend

underscore.reduce(obj, function(memo, o) { 
    return underscore.extend(memo, o); 
}, {}); 

,並得到了預期的結果:

{ x: 1, y: 2 } 

爲什麼有什麼區別? reduce期望作爲第二個參數的函數獲得兩個參數並返回一個,並且在兩種情況下都得到它。那麼我錯過了什麼?

回答

4

reduce預計隨着第二個參數是有兩個參數,並返回一個函數...

不按the documentation。下劃線經過迭代,而不是兩個,參數:

迭代器被傳遞四個參數:memo,則valueindex(或key)迭代的,最後一對整個list參考。

因此,你最終調用extend(在第一次通過)這樣的:

underscore.extend({}, {x: 1}, 'a', obj) 

,然後第二次通過

underscore.extend({/*...stuff...*/}, {y: 2}, 'b', obj) 

原因對象具有'0': 'b'屬性是該字符串可以擴展到包含'<index>': '<char>'等屬性的對象。這是因爲_.extend在每個參數上運行for...in...循環(除第一個參數外),通過對字符串進行操作而找到的鍵是字符索引(從0str.length - 1)。

+0

明白了。所以基本上我做了'underscore.extend({},{x:1},'a',obj);' – GilZ

+0

@Gil:Yup,第一遍。 :-) –

+1

當用'for ... in ...'循環(這是'_.extend'工作方式)循環時,字符串'「a」'只發出一個鍵 - 唯一字符的索引在字符串('0')中。例如,一個較長的字符串可以擴展爲''abc'' - >'{'0':'a','1':'b','2':'c'}'。 –

相關問題