TIL what the difference between angular’s watcher offerings are:
Angular watchers facilitate the 2 way data binding between views and controllers / services. Watchers bind listener functions to $scope properties (or expressions that evaluate to $scope properties). Bound
$scope properties are dirty-checked during each
$digest() cycle, and if a change in the property is detected the bound listener function is called.
There are a few different variations of watchers, each with different performance and purposes:
This is the most basic form of watcher. It accepts an expression as a string (either a
$scope property or expression that evaluates to a
$scope property) and a listener function to be called when the expression changes. This type of watcher only detects changes to shallow aspects of the bound
$scope property (reference equality via
=== comparison). This means if the bound
$scope property is an object, and a value in that object changes, the listener callback will not be called.
This registers a watcher for an array or object that is bound to $scope. If any item within the collection changes, including the addition or removal of a new item, the listener is called. Equality is determined using
=== between cycles.
The distinction between this watcher and
$watchCollection, is that
$watchGroup takes a group of expressions to watch instead of just one collection object. This can be useful if you need to bind a group of
$scope properties to the same listener callback (instead of needing to write different watchers for them all). For performance reasons,
$watchGroup delays calling the bound listener until the end of the
$digest() cycle, to wait and see if multiple items in the group change during
$digest() so the listener is only called once.
$watchGroup is only available in angular 1.3 onwards, so we don’t use it yet in our application (still on angular 1.2.27).
$watch can take a third boolean argument, which tells the watcher to use
angular.equals to check for deep objectEquality of the bound item. This causes the watcher to fire even when a sub-key or value of an object inside of the watched
$scope property changes.
$watch (objectEquality) uses
angular.equals for deep object comparison, it is the slowest performing of the watchers (deep comparison takes longer than shallow). For this reason, if you just need to watch a list of items and you don’t care about deep value changes in the list,
$watchGroup would better choices. Of course, if you just need to watch a single value (and shallow comparison will suffice)
$watch without objectEquality is the speediest option.
Bonus TIL: I also learned that registering a watcher on scope returns a deregistration function that can be used to remove the watcher from the digest cycle if it is no longer needed.
The next time
$scope.name changes, the watcher will not be registered so the alert will not occur. This is a good way to tidy up after yourself and reduce the length of the digest cycle, if watchers only need to exist temporarily or under certain conditions.
$watchCollection also returns a deregister function, so it can be used in the same way.