Javascript 控制器性能比较中的自定义过滤器与过滤器功能

Javascript 控制器性能比较中的自定义过滤器与过滤器功能,javascript,angularjs,performance,filter,angularjs-filter,Javascript,Angularjs,Performance,Filter,Angularjs Filter,假设我有一个5000个对象(带有布尔值)的数组,我必须在模板中ng repeat: $scope.arr = [ { "value": true }, { "value": false }, { "value": false } //and so on ] 现在,我想根据一个动态变量过滤这个ng repeated数组,比如'show_filter',我正在别处设置它 如果“show_filt

假设我有一个5000个对象(带有布尔值)的数组,我必须在模板中
ng repeat

$scope.arr = [
    {
        "value": true
    },
    {
        "value": false
    },
    {
        "value": false
    }
    //and so on
]
现在,我想根据一个动态变量过滤这个
ng repeated
数组,比如'show_filter',我正在别处设置它

如果“show_filter”设置为“all”,我想显示所有对象。如果设置为false(布尔值),则我希望显示“value”键设置为false的对象。当“show_filter”设置为true时也是如此

因此,有两种方法:

1。构建自定义筛选器:

我会为过滤任务编写一个自定义过滤器,如下所示:

过滤器:

2。在控制器中写入过滤函数:

过滤器:


以上两种方法中哪一种更快?我看到自定义筛选代码每次都会对每个摘要循环执行,而不仅仅是对
$scope.show\u filter
所做的更改,这让我相信它效率很低。虽然我不确定这两种方法之间哪个更快。

在每个摘要循环中都会调用这两个函数。对于第二个函数来说,这有点明显。
FilterObject(arr)
的返回值在每次调用时都可能不同

为什么在每个摘要周期中都会调用过滤器,这一点并不明显。文件规定如下:

filter函数应该是纯函数,这意味着它应该是无状态的幂等函数。Angular依赖于这些属性,仅当函数的输入更改时才执行过滤器

因此,如果
arr
show\u filter
都未更改,则不应调用过滤器,对吗?但这里有一个陷阱:检测
arr
中的变化代价高昂

Angular必须复制数组以将其与当前内容进行比较。即使没有任何变化,也必须对每一项进行比较。如果项目是对象,则必须对其每个属性进行比较。直接调用过滤器要便宜得多。这就是Angular在对数组(或对象)应用过滤器时所做的

要加速应用程序,您有两个选择。第一种方法是仅在必要时过滤数组,并将过滤后的数组公开给
ng repeat
。例如,如果您可以输入一个用于过滤数组的值,则在该值更改时过滤数组

如果阵列和过滤器都不改变(因此在您的情况下不改变),则可以使用第二种选择。然后可以使用一次性绑定:

<li ng-repeat="item in ::array | filter">

  • 当您有一组固定的项目,并希望按名称对其进行排序时,这非常有用,例如,在这种情况下,只会调用一次筛选器。

    您有两个相同的函数,您会询问哪一个最快?如果您的意思是调用次数最少,那么您可能已经回答了自己的问题?我不知道第二个函数调用了多少次。最快的方法是将过滤后的数组公开给
    ngRepeat
    。第二个函数必须在每个摘要周期中调用。数组根据外部变量进行过滤,外部变量可以通过事件随时设置。所以,我不认为我可以有一个预过滤数组。我认为最好的方法是对外部变量应用一个watch,并在watch的回调中过滤数组。你觉得呢?这就是我的意思。直接调用过滤器要便宜得多。这是指第一种方法还是第二种方法?此外,一次修正后,过滤器不能应用于对象。尽管如此,谢谢你澄清了很多事情!这适用于自定义过滤器(第一种方法)。过滤器可以应用于任何东西。想想
    date
    过滤器(日期是一个对象),或者
    json
    过滤器,它们只对对象有意义。顺便说一句,数组也是一个对象。
    obj in arr | filterArr : show_filter
    
    $scope.filterObjects = function(arr) {
        var filtered_arr = [];
        if($scope.show_filter != 'All') { //if $scope.show_filter is a boolean value
            for(var i = 0; i < arr.length; i++) {
                if(arr[i].value == $scope.show_filter) { 
                    filtered_arr.push(arr[i]);
                }
            }
            return filtered_arr;
        }
        else {
            return arr; //return the entire array if show_filter is set to 'All'
        }
    }
    
    obj in filterObjects(arr)
    
    <li ng-repeat="item in ::array | filter">