foreach循环递减索引中的JavaScript拼接函数

foreach循环递减索引中的JavaScript拼接函数,javascript,angularjs,Javascript,Angularjs,这是我从数组中删除“完成”TODO的代码, 但是,如果删除彼此后面的两个TODO,则只删除第二个TODO。 我认为这是因为splice函数重置并返回拼接的数组。您将数组中的元素拼接在一起,然后进行迭代,因此减少了“TODO”中的索引。对不起,我的英语不好 $scope.clearCompleted = function() { angular.forEach($scope.todos, function(todo, i) {

这是我从数组中删除“完成”TODO的代码, 但是,如果删除彼此后面的两个TODO,则只删除第二个TODO。
我认为这是因为splice函数重置并返回拼接的数组。

您将数组中的元素拼接在一起,然后进行迭代,因此减少了“TODO”中的索引。对不起,我的英语不好

$scope.clearCompleted = function()
        {
            angular.forEach($scope.todos, function(todo, i)
            {
                if(todo.done)
                {
                    $scope.todos.splice(i, 1);
                }
            });

            if($scope.todos.length == 0)
            {
                $scope.isEmpty = true;
            }
        }

这是因为
forEach
只知道数组的初始状态,因此调用您的方法两次,即使第一次调用从数组中删除了一个项。只需执行一个简单的while循环即可:

var notDonedTodos = [];
angular.forEach($scope.todos, function(todo, i)
{
    if(!todo.done)
    {
       notDonedTodos.push(todo);
    }
});

$scope.todos = notDonedTodos;

每次
迭代的问题是,它从数组中删除一个项,从而导致跳过迭代。jQuery有一个很好的
grep
方法,该方法返回符合由提供的匿名函数确定的特定条件的所有元素

var i = $scope.todos.length;
while (i--){
    if ($scope.todos[i].done){
        $scope.todos.splice(i, 1);
    }
}
工作示例


作为另一种选择,您可以在每次执行
拼接时减小索引。例如:

var todos =[{id:1, done:false},{id:2, done:true},{id:3, done:true}];

function removeCompleted(todos){
    return $.grep(todos,function(todo){
        return todo.done == false;
    });
}

todos = removeCompleted(todos);
console.log(todos);

这将在每次修改数组时调整索引以保持其有效性。您仍然可以使用
angular.forEach
,并且不会得到两个数组副本。

我发现自己的替代方法是使用array.filter方法。这是基于对象键过滤数组的最简单方法。如果你正在从事IE8项目(可怜的你),你需要为这个函数添加一个polyfill,因为它对JavaScript来说是相当新的

应答码:

$scope.clearCompleted = function() {
    angular.forEach($scope.todos, function(todo, i) {
        if(todo.done) {
            $scope.todos.splice(i, 1);
            i--;
        };
    });

    if($scope.todos.length == 0) {
        $scope.isEmpty = true;
    };
}

是的,
.splice()
会变异数组。如果使用正向迭代,则需要考虑到这一点。值得指出的是,此解决方案的诀窍在于数组是按相反顺序处理的,因此我们可以忽略数组长度的波动性。这同样适用于传统的for循环。
$scope.clearCompleted = function() {
    $scope.todos = $scope.todos.filter(function(item) {
        return !item.done;
    });
}