Angular defines a concept of a so called digest cycle. This cycle can
be considered as a loop, during which Angular checks if there are any
changes to all the variables watched by all the $scopes. So if you
have $scope.myVar defined in your controller and this variable was
marked for being watched, then you are explicitly telling Angular to
monitor the changes on myVar in each iteration of the loop.
Basically AngularJS binds event handlers to any element that interacts with Angular ($scope
, directive
, ...), every time the event fires, $apply
is called which internally calls $digest
which will trigger the re-evaluation of all the $watches
.
AngularJS made a smart assumption that model changes happen only on user interaction / events:
- DOM events
- XHR responses firing callbacks
- Browser's location changes
- Timers (setTimout, setInterval) firing the callbacks
Or trigger on certain events
- Input directives+ngModel, ngClick, ngMouseOver etc.
- $http and $resource
- $location
- $timeout

When one of these 'assumptions' is triggered, the digest cycle is kicked off:
To quote Pawel Kozlowski, Mastering Web Application Development with AngularJS:
AngularJS does not use any kind of polling mechanism to periodically
check for model changes
More detailed insights
Have a look at https://www.youtube.com/watch?v=SYuc1oSjhgY for a really deep dive into the digest cycle.