我试图压扁一个有两个对象的对象,所以我做了以下几点:
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
期望作为第二个参数获得两个参数并返回一个参数,并且在两种情况下都获得它。那我错过了什么?
答案 0 :(得分:4)
reduce
期望作为第二个参数获得两个参数并返回一个...
不符合the documentation。 Underscore传递迭代器四个,而不是两个参数:
迭代器传递四个参数:
memo
,然后是迭代的value
和index
(或key
),最后是对整个{的引用{1}}。
因此,您最终会调用list
(在第一次传递时),如下所示:
extend
然后是第二遍
underscore.extend({}, {x: 1}, 'a', obj)
对象具有underscore.extend({/*...stuff...*/}, {y: 2}, 'b', obj)
属性的原因是字符串扩展到包含'0': 'b'
等属性的对象。这是因为'<index>': '<char>'
在每个参数(第一个除外)上运行_.extend
循环,并且通过对字符串执行此操作而找到的键是字符索引(从for...in...
到{{1} })。