What You’ll Learn
What $watch
and $watchCollection
do
Key differences between them
When to use each one efficiently
Performance optimization tips
1️⃣ Understanding $watch
in AngularJS
What is $watch
?
$watch
monitors a scope variable and runs a function when its value changes.- It can track primitive values, objects, and arrays.
Syntax
$scope.$watch('variableName', function(newValue, oldValue) {
console.log('Value changed:', oldValue, '➡', newValue);
});
Example: Watching a Primitive Value
$scope.name = "Narendra";
$scope.$watch('name', function(newVal, oldVal) {
console.log("Name changed from", oldVal, "to", newVal);
});
Efficient for simple values like string
, number
, or boolean
.
Watching an Object (Deep Watch)
By default, $watch
does not track object properties deeply.
To watch an entire object, pass true
as the third argument.
$scope.user = { name: "Narendra", age: 25 };
$scope.$watch('user', function(newVal, oldVal) {
console.log("User changed:", newVal);
}, true); // Deep watch
Deep watch (true
) makes performance slower. Use it only when necessary.
2️⃣ Understanding $watchCollection
What is $watchCollection
?
$watchCollection
is optimized for arrays and objects.- It tracks changes to top-level properties but does not deep-watch nested properties.
Syntax
$scope.$watchCollection('arrayOrObject', function(newVal, oldVal) {
console.log("Collection changed:", newVal);
});
Example: Watching an Array Efficiently
$scope.items = ["Apple", "Banana", "Cherry"];
$scope.$watchCollection('items', function(newVal, oldVal) {
console.log("Array updated:", newVal);
});
Optimized for tracking additions/removals in arrays.
Problem with $watch
for arrays:
$scope.$watch('items', function(newVal, oldVal) {
console.log("Array updated:", newVal);
}, true); // Deep watch (expensive)
Optimized alternative:
$scope.$watchCollection('items', function(newVal, oldVal) {
console.log("Array changed:", newVal);
});
$watchCollection
detects new elements, removed elements, or reference changes, but not deep changes inside objects within the array.
3️⃣ Key Differences Between $watch
and $watchCollection
Feature | $watch | $watchCollection |
---|---|---|
Tracks primitive values | Yes | Yes |
Tracks entire objects | (With true ) | (Only top-level properties) |
Detects nested changes | (With deep watch) | No |
Works well with arrays | No (Expensive deep watch needed) | Yes (Efficient) |
Best for simple values | Yes | Yes |
Best for arrays & collections | No | Yes |
4️⃣ When to Use $watch
vs $watchCollection
?
Use $watch when… | Use $watchCollection when… |
---|---|
Watching a primitive value (string , number , boolean ). | Tracking array length changes (adding/removing items). |
Watching an entire object deeply (if you use true ). | Watching objects without deep tracking. |
Tracking nested property changes (user.address.city ). | Tracking top-level object property changes. |
5️⃣ Performance Optimization Tips
1. Avoid Deep Watches When Possible
- Deep watches (
true
) are expensive and slow down performance. - Instead, watch only the required properties.
Bad (Deep Watch on Large Object):
$scope.$watch('user', function(newVal, oldVal) {
console.log("User updated");
}, true); // Deep watch (slow)
Optimized (Watch Only Required Property):
$scope.$watch('user.name', function(newVal, oldVal) {
console.log("User name updated");
});
Reduces unnecessary digest cycle runs.
2. Use $watchCollection
for Arrays Instead of Deep Watching
Good:
$scope.$watchCollection('items', function(newVal, oldVal) {
console.log("Array updated:", newVal);
});
Bad (Expensive Deep Watch on Array):
$scope.$watch('items', function(newVal, oldVal) {
console.log("Array updated");
}, true); // Deep watch (slow)
$watchCollection
is faster for tracking array additions/removals.
3. Use One-Time Binding (::
) for Static Data
If a value never changes, use one-time binding in templates to remove watchers.
<h1>{{ ::title }}</h1> <!-- Only evaluated once -->
Removes unnecessary watchers, improving performance.
4. Use $timeout()
Instead of $apply()
to Prevent Extra Digest Cycles
When updating scope asynchronously, avoid $apply()
as it triggers a full digest cycle.
Bad:
setTimeout(function () {
$scope.message = "Updated";
$scope.$apply(); // Forces a full digest cycle
}, 1000);
Optimized:
$timeout(function () {
$scope.message = "Updated"; // Triggers digest automatically
}, 1000);
$timeout()
schedules updates without forcing an extra digest cycle.
6️⃣ Final Summary
Aspect | $watch | $watchCollection |
---|---|---|
Best for | Primitives, individual properties | Arrays, object top-level properties |
Tracks deep changes? | Yes (with true ) | No |
Performance impact | Higher (with deep watch) | Lower |
Replaces deep watch for arrays? | No | Yes |
Alternative to $watch(true) ? | No | Yes |