lodash中map和max的奇怪行为

时间:2013-10-29 11:03:31

标签: javascript lodash

var a = [ [1,2,3], [4,5,6], [7,8,9] ];
_.map( a, _.max );
// gives [3, -Infinity, -Infinity]

我已经在lodash网站上的Chrome浏览器上进行了测试。

上面的代码不应该返回[3,6,9]吗?

我可以使用forEach获得正确的结果:

var a = [ [1,2,3], [4,5,6], [7,8,9] ];
var result = [];
_.forEach( a, function(arr) { result.push(_.max(arr)); } );

1 个答案:

答案 0 :(得分:5)

总体结论

我在GitHub上打开了一个问题:https://github.com/lodash/lodash/issues/379
感谢jdalton,问题现已解决。示例:→jsFiddle

详情(为什么结果'怪异'?)

我从未详细介绍过Lodash,但这是我的研究:

  

检索集合的最大值。如果集合为空或假冒-Infinity,则返回。{    - Lodash Documentation: _.max()

每个小组的_.max()测试都非常完美:

_.max([1,2,3]);  // 3
_.max([4,5,6]);  // 6
_.max([7,8,9]);  // 9

现在,我尝试在_.max()的回调函数中手动调用_.map()

var a = [ [1,2,3], [4,5,6], [7,8,9] ];
alert(_.map( a, function(val) {
    return _.max(val);
}));

工作正常!那么它与_.max()作为第二个参数之间的区别在哪里呢?
_.map()实际上向回调函数发送了3个参数:

  

(值,索引|键,集合)    - Lodash Documentation: _.map()

现在考虑_.max()的第二个参数:

  

2. [callback = identity](函数|对象|字符串):每次迭代调用的函数。如果提供属性名称或对象,它将是   用于分别创建“.pluck”或“.where”样式回调    - Lodash Documentation: _.max()

结论: _.max()也会传递_.map()提供的第二个和第三个参数。第二个参数在这里很重要!为它传递真值(例如整数!= 0)让函数返回-Infinity

测试用例(→ jsFiddle):

alert(_.max([1,2,3], 0)); // 3
alert(_.max([1,2,3], 1)); // -Infinity
alert(_.max([1,2,3], 2)); // -Infinity

这来自源代码中执行的布尔检查: https://github.com/lodash/lodash/blob/f0f7eee963966516490eb11232c9e9b4c6d0cc6c/dist/lodash.js#L3431

因为callback(第二个参数)是一个真值,我们将直接跳转到 else 分支。在那里,callback被重新分配为以下(三元操作也将采用 else 分支):

lodash.createCallback(callback, thisArg, 3);

createCallback()定义为here。 它为我们的特定输入参数返回以下函数(这些参数为1, null, 3,有关详细信息,请参阅_.max()):

return function(object) {
  return object[func];
};

比方说,我们将其保存在名为callback→ jsFiddle)的变量中:

var callback = _.createCallback(1, null, 3);

使用object = 1(或2,3或6等)调用该函数会导致undefined(这很明显)。

回到_.max(),我们看到有一个循环将当前值(来自回调函数)与初始/最后一个值进行比较,即{{1在函数的开头设置。

-Infinity永远不会导致 true ,因此undefined > -Infinity将保持“最大”值。