为什么下划线.在这两种情况下,Reduce的作用是不同的

Why does underscore.reduce acts differently in these two cases?

本文关键字:Reduce 作用 是不同 情况下 下划线 两种 为什么      更新时间:2023-09-26

我试图将一个有两个对象的对象压平,所以我做了以下操作:

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期望作为第二个参数的函数获得两个参数并返回一个,并且它在两种情况下都得到它。那么我错过了什么呢?

reduce期望作为第二个参数,一个函数获得两个参数并返回一个…

根据文档没有。下划线传递给迭代器四个参数,而不是两个:

传递给迭代器四个参数: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)。