【问题标题】:Array find, natively or through jQuery?数组查找,本机还是通过 jQuery?
【发布时间】:2013-01-16 16:05:42
【问题描述】:

你会做这种事吗?

    var getBoard1 = function(id) {
        return $.grep(me.boards, function (board) {
            return board.Id == id;
        });
    };

还是这样的?

    var getBoard2 = function(id) {
        for (var i = 0; i < me.boards.length; i++) {
            var board = me.boards[i];
            if (board.Id == id)
                return board;
        }
        return null;
    };

为什么,在正确性、可读性和性能方面,您更喜欢这种方式?如果您愿意以第三种方式进行,请分享。

【问题讨论】:

  • 在这里测量:jsperf.com
  • 我做了一个对比:jsperf.com/grep-vs-pure-js
  • 哇,dfsq! getBoard2 比 getBoard1 快 5.4 倍。把我的袜子踢掉了。谢谢! :)
  • 请注意,它们与第一个返回数组和第二个返回对象并不完全相同
  • @DavidFregoli 是的。我终于也注意到了。所以我们必须检查 grep 的长度,把 getBoard1 弄混了一点。

标签: javascript jquery performance


【解决方案1】:

这是grep 函数的样子(jQuery v1.8.2):

grep: function( elems, callback, inv ) {
    var retVal,
        ret = [],
        i = 0,
        length = elems.length;
    inv = !!inv;

    // Go through the array, only saving the items
    // that pass the validator function
    for ( ; i < length; i++ ) {
        retVal = !!callback( elems[ i ], i );
        if ( inv !== retVal ) {
            ret.push( elems[ i ] );
        }
    }

    return ret;
}

基本上,您正在做同样的事情,因此在性能方面不会有太大差异。当我查看 jQuery 代码时,它们总是返回一个数组,您在其中返回 null。如果你已经在使用 jQuery,我会选择 jQuery 版本,因为它可读性更好,否则使用 native 代码。

* -- 编辑 -- *

查看代码时,这让我意识到它确实有所作为。您的代码在找到第一项(只期望一个结果)时已经返回(并完成循环),其中 jQuery 循环遍历 all 项。因此,如果您只期望一个结果,您的版本会更快。

【讨论】:

  • 查看 dfsq 的链接,显示性能提升。我猜这将是构建一次性数组和包装函数调用的开销。
  • 也更新了我的答案 - 它确实有所作为。
【解决方案2】:

jQuery 提供了方便的方法,在后台它可能会做类似的事情。如果您已经在使用 jQuery,那么您可以利用这一点,但是我不会仅仅为这样的一点代码包含 jQuery。这完全取决于您的情况。

至于性能,试试看,看看结果如何。

【讨论】:

    【解决方案3】:

    如果您已经对 jQuery 有依赖,那么请使用第一种方式,因为它更短且更易于阅读。在极不可能的情况下,此功能是您的瓶颈并且性能无法接受,那么您可以开始考虑替代实现。

    如果您还没有依赖 jQuery,那么第二个版本更可取,因为这种权衡(包括 jQuery 与编写更多代码行)是不值得的。

    【讨论】:

    • 有趣。你会说 getBoard1 对于没有 nix 背景的新手来说更具可读性吗?我认为 grep 会很快击中谷歌......简短很好,但明确也可以同样好,不是吗?
    • @Mithon:取决于新手。您无需了解 jQuery 即可识别谓词回调,如果您这样做,即使 $.grep 完全未知,该方法的作用也很明显。但这不是我在回答时的想法——问题并没有说“如果新手要维护它,你更喜欢什么代码”。
    • 不,但我确实提到了可读性。我想我认为在与新手打交道时可读性是双重重要的,所以这是暗示的。我的错。但是,如果它对新手来说更容易,那么对老年人来说也会更容易。 :)
    • @Mithon:不一定......客户端JS都是关于回调的,对于老年人恕我直言,最好让代码是惯用的。他们应该像阅读他们的母语一样阅读这样的简单代码。
    • 你说得有道理。在可读性部分赢得了我的青睐。然而,5.4 倍的减速.. 不.. 它是原生的
    【解决方案4】:

    我会使用原生的Array.filter(),如果你不关心浏览器支持,这可能是最快的(IE8- 会死在这里)。

    a.filter(function(e){return e.id == id});
    

    这返回,就像 jQuerys grep 一个数组,你必须在其中获取第一个值。

    【讨论】:

    • 虽然乍一看这看起来不错,但您必须添加代码来检查结果数组是否为非空,如果不是则返回第一个元素。所以它的清洁度会丢失。
    • 好吧,无论您采用哪种方法,都必须在每种情况下进行检查,并且编写if(board)(自定义方法检查null)或@987654325真的没关系@ (.filter),是吗? jQuerys grep 也返回一个数组,所以你也需要用if(board[0]):-p 来检查这个
    • 当然可以。在这两种意义上。如果方法返回一个数组,那些 if 将返回不同的结果。如果您的意思是如果我们将 getBoard 的含义更改为返回一个数组而不是一个单板并没有什么不同,那么我强烈不同意。像这样命名的函数肯定会让人们假设他们会得到一个单板,而不是一个数组,因此几个月后出现的下一个程序员可能会写错 if-test。下一个程序员可能就是我自己。
    • @Mithon 好吧,显然你不知道 jQuerys grep 是如何工作的。实际上它返回一个数组,就像 Array.filter 一样。因此,两种方法的必要检查完全相同……如果您愿意,请将其包装在一个附加的函数包装器return a[0] || null 中,然后您就有了标量返回值。现在随意撤销您的 -1。
    • 我愿意。虽然我没有立刻意识到。请参阅上面我对大卫的评论。是的,这会使 getBoard1 变得混乱,就像您的解决方案会稍微混乱一样。 :) 郑重声明,我没有给你投反对票。事实上,我会给你一个。毕竟我确实要求过其他方式。
    猜你喜欢
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 2011-07-31
    相关资源
    最近更新 更多