实现 _.every 方法
我试图掌握下面的代码是如何实现的。
_.every = function(collection, iterator) {
var check = iterator || _.identity;
if (collection.length === 0) {
return true;
}
// check if any are falsy
return _.reduce(collection, function (prev, next) {
if (!prev) {
return false;
} else {
return check(next) ? true : false;
}
}, true);
};
我熟悉 reduce 以及它如何接受 accumulator
作为最后一个 argument
,但我还没有看到 bool
作为该参数传递。
此外,reduce 中的 if
语句有点令人困惑,因为 reduce
将传递累加器,在这种情况下它是 true
,因为第一个iterator
中用于 reduce 的参数。所以:
if(!prev)
真正的意思是 if(!true)
,如果不为真则返回 false。
这会结束 reduce 函数吗?还是会转到 else 语句?
任何有助于阐明此代码中发生的事情的帮助,或如何实现 _.every
的更好示例将不胜感激。
最佳答案
reduce 函数为输入集合的每个元素调用它的函数参数。 prev
第一次调用 reduce 中的匿名函数时为真,但不一定是第二次和第三次。
例如,假设 every
用于检查数据库中的所有发票是否已支付。如果一千张发票中的第二张尚未支付,则无需联系数据库服务器获取第三张和更多的元素。
首先检查是否prev
已经是假的(因此结果将是假的),这个实现避免了进一步的需要。可以说,在检测到 false 时,该函数甚至可以在那里停止处理,不再继续处理,但唉 reduce
不提供该选项。
例如,假设我们调用 _.every([1,2,3,4,5,6], function(i) {return i < 3;});
:
accumulator | input | result | check called?
=============================================
true | 1 | true | yes
true | 2 | true | yes
true | 3 | false | yes
false | 4 | false | no
false | 5 | false | no
false | 6 | false | no
累加器是 reduce
的参数( true
) 在第一轮中,在后一轮中是上一轮的结果。整个函数的结果是 result
的最后一个条目专栏。
return check(next) ? true : false;
是
if (check(next)) {
return true;
} else {
return false;
}
或者,可以简单地写成 !!check(next)
.三个版本的效果是一样的——转换check(next)
bool 值。
另一种编写整个函数的方法是:
_.every = function(collection, iterator) {
var check = iterator || _.identity;
return _.reduce(collection, function (prev, next) {
return prev && !!check(next);
}, true);
};
这里我们使用 short-circuit operator &&
几乎相同的效果。请注意,我们可以安全地删除 collection.length === 0
的检查。 ,因为 reduce 将简单地返回初始累加器(又名 memo
)。
如上所述,一旦我们知道结果将是假的,更快的方法是中止(请注意,这个特定版本可能只适用于数组):
_.every = function(collection, iterator) {
var check = iterator || _.identity;
for (var i = 0;i < collection.length;i++) {
if (! check(collection[i])) {
return false;
}
}
return true;
};
关于javascript - 下划线 - _.every 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34890723/