javascript - 下划线 - _.every 实现

标签 javascript function functional-programming underscore.js implementation

实现 _.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;
};

这就是我们 see in 的实现(尽管有些简化) the wild .

关于javascript - 下划线 - _.every 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34890723/

相关文章:

loops - for/继续方案/lisp

javascript - 使用 setInterval 每 60 秒保存一次表单不起作用

javascript - 我在从 React bootstrap 导入按钮时遇到问题

javascript - If() block 更改接收到的 Meteor 数据

javascript - 单击子元素而不是父元素时切换

c - 必须在 C 中声明函数原型(prototype)吗?

javascript - 为什么函数变量计算结果返回错误?

php - Ckeditor/PHP 中的 WordPress 风格简码

r - 将矩阵划分为 R 中的列表时出现奇怪的输出

swift - 在 Swift 中使用 reduce 构建字典