Assuming that the process is in steps which require user interaction, the steps will be as follows. Note that the numbers in the indented lists represent the high level process that Angular uses.
- Angular renders view with default array [obj1, obj2, ob3]
- A watcher is created which watches array reference
- Angular sets up watchers on the total array of objects
- Watcher also watches properties of objects within the array
- User interacts with view, causing array to be set to []
- Watcher #1 above fires on new array reference, builds watchers for any new objects and deconstructs watchers for old references.
- User interacts again to build new array of items with one property change [obj1, obj2′, obj3].
- Watcher #1 fires, noticing a new array reference
- Angular builds watchers for each object and properties of those objects within the array
In terms of speed, step #2 is essentially a NoOP. What you're probably running into is the time it takes Angular to construct and deconstruct the watchers when a new array of objects is created.
When angular sets up a watcher on an object or an array of objects it'll add in a $hash property to all objects within the array. Now imagine that a new array is created which looks the same as the old one but all of the object references in memory are new and the $hashes are gone or changed. This causes Angular to fire all of the $watch statements for that scope variable.
You shouldn't be creating a new array or assigning the original scope array to a new value. This is a bad pattern. The code below shows two methods: one which will cause the watchers to fire more than desirable, and a better method which will only fire the watchers that need to be fired.
scope.myArr = [{n:1, a:true}, {n:2, a:true}, {n:3, a:true}];
//BAD PATTERN
scope.doSomething = function(n){
scope.myArr = [];
//somehow it gets a new array
getNewArrayFromAPI(n)
.then(function(response){
scope.myArr = response.data;
});
//[{n:1, a:true}, {n:2, a:false}, {n:3, a:true}]
}
//user interaction
scope.doSomething(2);
The following good pattern updates the array in place, never changing the references to the original objects unless it needs to add a new object to the array.
//GOOD PATTERN
scope.myArr = [{n:1, a:true}, {n:2, a:true}, {n:3, a:true}];
scope.doSomething = function(n){
//this method shows an in-place non-HTTP change
scope.myArr.forEach(function(curr){
if(curr.n === n){
curr.a = false;
}
});
scope.getChangedArray(n);
};
//represents an HTTP call, POST or PUT maybe that updates the array
scope.getChangedArray = function(n){
$http.post("/api/changeArray", n)
.then(function(response){
//response.data represents the original array with n:2 changed
response.data.forEach(function(curr){
var match = scope.myArr.filter(function(currMyArr){
return currMyArr.n === curr.n;
});
if(match.length){
//update the existing properties on the matched object
angular.extend(match[0], curr);
}else{
//new object
scope.myArr.push(curr);
}
});
})
};
//user interaction
scope.doSomething(2);