$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;
}
}
这是我从数组中删除'done'待办事项的代码, 但是当两个相互之后的todos被移除时,它只会移除第二个。 我认为这是因为splice函数重置并返回拼接数组。
答案 0 :(得分:18)
您从迭代的数组中拼接元素,因此“todos”中的索引减少了。对不起,我的英语不好。
var notDonedTodos = [];
angular.forEach($scope.todos, function(todo, i)
{
if(!todo.done)
{
notDonedTodos.push(todo);
}
});
$scope.todos = notDonedTodos;
答案 1 :(得分:18)
这种情况正在发生,因为forEach
只知道数组的初始状态,因此调用您的方法两次,即使第一次调用从数组中删除了一个项目。只需做一个简单的while循环:
var i = $scope.todos.length;
while (i--){
if ($scope.todos[i].done){
$scope.todos.splice(i, 1);
}
}
答案 2 :(得分:7)
替代方案我发现自己是使用array.filter方法。这是基于对象键过滤数组的最简单方法。如果你正在开发一个IE8项目(你很差),你需要为这个函数添加一个polyfill,因为它对于JavaScript来说还算新。
Everything you need to know about javascript
答案代码:
$scope.clearCompleted = function() {
$scope.todos = $scope.todos.filter(function(item) {
return !item.done;
});
}
答案 3 :(得分:3)
each
迭代的问题是它从数组中删除了一个项,导致跳过迭代。 jQuery有一个很好的grep
方法,它返回所有符合特定条件的元素,这些元素由提供的匿名函数确定。
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);
答案 4 :(得分:2)
作为另一种选择,您可以在每次执行splice
时减少索引。例如:
$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;
};
}
每次修改数组时,都会调整索引以保持其有效性。您仍然可以使用angular.forEach
,并且最终不会得到阵列的两个副本。