2014-06-12 192 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'}'。 –

相关问题