whole_func_string: function(watchExpressions, listener) {
          var oldValues = new Array(watchExpressions.length);
          var newValues = new Array(watchExpressions.length);
          var deregisterFns = [];
          var self = this;
          var changeReactionScheduled = false;
          var firstRun = true;
  
          if (!watchExpressions.length) {
            // No expressions means we call the listener ASAP
            var shouldCall = true;
            self.$evalAsync(function() {
              if (shouldCall) listener(newValues, newValues, self);
            });
            return function deregisterWatchGroup() {
              shouldCall = false;
            };
          }
  
          if (watchExpressions.length === 1) {
            // Special case size of one
            return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
              newValues[0] = value;
              oldValues[0] = oldValue;
              listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
            });
          }
  
          forEach(watchExpressions, function(expr, i) {
            var unwatchFn = self.$watch(expr, function watchGroupSubAction(value) {
              newValues[i] = value;
              if (!changeReactionScheduled) {
                changeReactionScheduled = true;
                self.$evalAsync(watchGroupAction);
              }
            });
            deregisterFns.push(unwatchFn);
          });
  
          function watchGroupAction() {
            changeReactionScheduled = false;
  
            try {
              if (firstRun) {
                firstRun = false;
                listener(newValues, newValues, self);
              } else {
                listener(newValues, oldValues, self);
              }
            } finally {
              for (var i = 0; i < watchExpressions.length; i++) {
                oldValues[i] = newValues[i];
              }
            }
          }
  
          return function deregisterWatchGroup() {
            while (deregisterFns.length) {
              deregisterFns.shift()();
            }
          };
        }
func_code_string: function(watchExpressions, listener) {
          var oldValues = new Array(watchExpressions.length);
          var newValues = new Array(watchExpressions.length);
          var deregisterFns = [];
          var self = this;
          var changeReactionScheduled = false;
          var firstRun = true;
  
          if (!watchExpressions.length) {
            // No expressions means we call the listener ASAP
            var shouldCall = true;
            self.$evalAsync(function() {
              if (shouldCall) listener(newValues, newValues, self);
            });
            return function deregisterWatchGroup() {
              shouldCall = false;
            };
          }
  
          if (watchExpressions.length === 1) {
            // Special case size of one
            return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
              newValues[0] = value;
              oldValues[0] = oldValue;
              listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
            });
          }
  
          forEach(watchExpressions, function(expr, i) {
            var unwatchFn = self.$watch(expr, function watchGroupSubAction(value) {
              newValues[i] = value;
              if (!changeReactionScheduled) {
                changeReactionScheduled = true;
                self.$evalAsync(watchGroupAction);
              }
            });
            deregisterFns.push(unwatchFn);
          });
  
          function watchGroupAction() {
            changeReactionScheduled = false;
  
            try {
              if (firstRun) {
                firstRun = false;
                listener(newValues, newValues, self);
              } else {
                listener(newValues, oldValues, self);
              }
            } finally {
              for (var i = 0; i < watchExpressions.length; i++) {
                oldValues[i] = newValues[i];
              }
            }
          }
  
          return function deregisterWatchGroup() {
            while (deregisterFns.length) {
              deregisterFns.shift()();
            }
          };
        }
func_documentation_string: @ngdoc method
  @name $rootScope.Scope#$watchGroup
  @kind function
  
  @description
  A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
  If any one expression in the collection changes the `listener` is executed.
  
  - The items in the `watchExpressions` array are observed via the standard `$watch` operation. Their return
  values are examined for changes on every call to `$digest`.
  - The `listener` is called whenever any expression in the `watchExpressions` array changes.
  
  @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
  watched using {@link ng.$rootScope.Scope#$watch $watch()}
  
  @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
  expression in `watchExpressions` changes
  The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
  those of `watchExpression`
  and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
  those of `watchExpression`
  The `scope` refers to the current scope.
  @returns {function()} Returns a de-registration function for all listeners.