As previously stated, Angular watches changes to the model to ensure that it captures all of them. It will look for any changes between the previous state of the overall application model and the current state.
Angular raises the following question in the default change detection strategy: Has any value in the model changed? However, with a reference type, we can use strategies to ask a better query. The OnPush change detection method comes into play here.
onPush Strategy
The OnPush technique is based on the notion that treating reference types like immutable objects allows us to notice changes in values much faster. When a reference type is immutable, it indicates that the reference on the stack memory must change every time it is updated. Now we can simply check: Has the reference type's reference (in the stack) changed? If this is the case, double-check all the values (on the heap). If we are having trouble understanding this, go back to the previous stack heap diagrams.
Instead of asking one question, the OnPush approach asks two. Has there been a change in the reference type's reference? Have the values in heap memory changed if this is the case?
Assume we have a 30 element immutable array, and we want to determine if there have been any changes. We know that in order for the immutable array to be updated, the reference to it (in the stack) would have to change. This means we can check to see if the array reference is different right away, potentially saving us 30 more tests (in the heap) to figure out which element is different. The OnPush approach is what it's called.
So, what does it mean to treat reference types as immutable, we might ask? It means we never set a reference type's property, but instead reassign the value as a whole. Take a look at what follows:
Treating objects as mutable:
static mutable() {
var before = {foo: "bar"};
var current = before;
current.foo = "hello";
console.log(before === current);
// => true
}
Treating objects as immutable:
static mutable() {
var before = {foo: "bar"};
var current = before;
current = {foo "hello"};
console.log(before === current);
// => false
}
It's worth noting that in the examples above, we're treating reference types as immutable by convention, so we're still dealing with changeable objects at the end of the day.
So, how do we put an OnPush strategy into action for a component? Simply include the changeDetection argument in their @Component annotation.
import {ChangeDetectionStrategy, Component} from '@angular/core';
@Component({
// ...
changeDetection: ChangeDetectionStrategy.OnPush
})
export class OnPushComponent {
// ...
}