Counting the number of watchers on a page in angular.js

A large number of angular.js watchers are usually the source of slowdowns in angular build applications. When using {{foo}} or $scope.$watch(...) angular will create a new watcher to check for changes on each $digest cycle and be able to notify the controller or update the view. It is generally accepted that once the number of watchers reaches 2000+, an application will start to suffer.

With the following, you can count the number of watchers on a page.

(function (window) {
  var slice = [].slice;
  window.ngWatchCount = function (base) {
    var elems;
    if (base && typeof base !== 'string') {
      elems = slice.call(base.querySelectorAll('*'));
      elems.unshift(base);
    } else if (typeof base === 'string') {
      elems = slice.call(document.querySelectorAll(base + ', ' + base + ' *'));
    } else {
      elems = slice.call(document.querySelectorAll('*'));
    }
    return elems
      .map(function (elem) {
        var data = angular.element(elem).data();
        //if (data.$scope && data.$scope.$$watchers && data.$scope.$$watchers.length) {
        //  elem.setAttribute("angular-watch-count", data.$scope.$$watchers.length);
        //}
        return data.$scope || null;
      })
      .filter(function (scope) {
        return scope && scope.$$watchers;
      })
      .reduce(
        function (tmp, scope) {
          if (tmp.cache[scope.$id]) {
            return tmp;
          }
          tmp.cache[scope.$id] = true;
          tmp.count += scope.$$watchers.length;
          return tmp;
        },
        {
          count: 0,
          cache: {},
        },
      ).count;
  };
})(window);

// usage
// ngWatchCount(document.getElementById("foo")) => 200 (passing a dom element)
// ngWatchCount(".some-qsa-query") => 900              (passing a querySelectorAll selector string, selector included)
// ngWatchCount() == ngWatchCount(document) => 1400    (no argument, will find all watches)

Just paste it in the console or put it in some debug block on the page.