In AngularJS, $watch
and $watchCollection
are used to monitor changes in scope variables. While $watch
is powerful, it can have performance implications when dealing with objects. $watchCollection
provides a more optimized approach for tracking shallow changes in an object or array.
1. Understanding $watch
and Its Limitations
Example of $watch
Monitoring an Object
$scope.user = { name: "John", age: 25 };
$scope.$watch("user", function(newVal, oldVal) {
if (newVal !== oldVal) {
console.log("User object changed:", newVal);
}
}, true);
How It Works?
$watch
is tracking deep changes (sincetrue
is passed as the third parameter).- Any change within the object, including nested properties, will trigger the watcher.
- Performance Issue:
- It uses deep object comparison, leading to frequent digest cycle executions.
- Slows down performance when tracking large objects.
2. Optimizing Performance with $watchCollection
Using $watchCollection
for Shallow Object Tracking
$scope.user = { name: "John", age: 25 };
$scope.$watchCollection("user", function(newVal, oldVal) {
if (newVal !== oldVal) {
console.log("User object changed:", newVal);
}
});
How $watchCollection
Works?
- It only tracks the first-level (shallow) properties of the object.
- If a property value at the first level changes, the function runs.
- It does not track nested object changes.
Performance Benefits of $watchCollection
✔ Lighter execution than $watch
(deep watch).
✔ Avoids unnecessary digest cycles.
✔ Faster in tracking arrays and objects with shallow updates.
3. $watch
vs. $watchCollection
– Key Differences
Feature | $watch (Deep Watch) | $watchCollection (Shallow Watch) |
---|---|---|
Tracks Nested Changes? | Yes (with true flag) | No (only first-level changes) |
Performance Impact | Higher CPU load due to deep checking | Lower impact (tracks shallow changes) |
Best for? | Complex objects needing full tracking | Simple object/array modifications |
Use Case | Watching deeply nested objects | Monitoring collections like lists, arrays |
4. Example: Watching an Array Efficiently
Inefficient Approach Using $watch
(Deep Watch)
$scope.items = ["Apple", "Banana", "Cherry"];
$scope.$watch("items", function(newVal, oldVal) {
console.log("Items changed:", newVal);
}, true); // Deep watch
Problem:
- This will trigger even when only one item in the array changes.
- Expensive for large arrays.
Optimized Approach Using $watchCollection
$scope.items = ["Apple", "Banana", "Cherry"];
$scope.$watchCollection("items", function(newVal, oldVal) {
console.log("Items changed:", newVal);
});
✔ Efficient Tracking:
- Detects changes when an item is added, removed, or replaced.
- Does not track deep changes inside objects within the array.
5. When to Use $watchCollection
?
Use Case | Best Choice |
---|---|
Tracking changes in a large array | $watchCollection |
Detecting first-level changes in objects | $watchCollection |
Watching deeply nested objects | Use $watch (deep watch) |
Reducing performance overhead | $watchCollection |