function $watchCollectionWatch() {
          newValue = objGetter(self);
          var newLength, key;

          if (!isObject(newValue)) { // if primitive
            if (oldValue !== newValue) {
              oldValue = newValue;
              changeDetected++;
            }
          } else if (isArrayLike(newValue)) {
            if (oldValue !== internalArray) {
              // we are transitioning from something which was not an array into array.
              oldValue = internalArray;
              oldLength = oldValue.length = 0;
              changeDetected++;
            }

            newLength = newValue.length;

            if (oldLength !== newLength) {
              // if lengths do not match we need to trigger change notification
              changeDetected++;
              oldValue.length = oldLength = newLength;
            }
            // copy the items to oldValue and look for changes.
            for (var i = 0; i < newLength; i++) {
              var bothNaN = (oldValue[i] !== oldValue[i]) &&
                  (newValue[i] !== newValue[i]);
              if (!bothNaN && (oldValue[i] !== newValue[i])) {
                changeDetected++;
                oldValue[i] = newValue[i];
              }
            }
          } else {
            if (oldValue !== internalObject) {
              // we are transitioning from something which was not an object into object.
              oldValue = internalObject = {};
              oldLength = 0;
              changeDetected++;
            }
            // copy the items to oldValue and look for changes.
            newLength = 0;
            for (key in newValue) {
              if (newValue.hasOwnProperty(key)) {
                newLength++;
                if (oldValue.hasOwnProperty(key)) {
                  if (oldValue[key] !== newValue[key]) {
                    changeDetected++;
                    oldValue[key] = newValue[key];
                  }
                } else {
                  oldLength++;
                  oldValue[key] = newValue[key];
                  changeDetected++;
                }
              }
            }
            if (oldLength > newLength) {
              // we used to have more keys, need to find them and destroy them.
              changeDetected++;
              for(key in oldValue) {
                if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) {
                  oldLength--;
                  delete oldValue[key];
                }
              }
            }
          }
          return changeDetected;
        }
@ngdoc method
@name $rootScope.Scope#$watchCollection
@function

@description
Shallow watches the properties of an object and fires whenever any of the properties change
(for arrays, this implies watching the array items; for object maps, this implies watching
the properties). If a change is detected, the `listener` callback is fired.

- The `obj` collection is observed via standard $watch operation and is examined on every
  call to $digest() to see if any items have been added, removed, or moved.
- The `listener` is called whenever anything within the `obj` has changed. Examples include
  adding, removing, and moving items belonging to an object or array.


# Example
```js
          $scope.names = ['igor', 'matias', 'misko', 'james'];
          $scope.dataCount = 4;

          $scope.$watchCollection('names', function(newNames, oldNames) {
            $scope.dataCount = newNames.length;
          });

          expect($scope.dataCount).toEqual(4);
          $scope.$digest();

          //still at 4 ... no changes
          expect($scope.dataCount).toEqual(4);

          $scope.names.pop();
          $scope.$digest();

          //now there's been a change
          expect($scope.dataCount).toEqual(3);
```


@param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
   expression value should evaluate to an object or an array which is observed on each
   {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
   collection will trigger a call to the `listener`.

@param {function(newCollection, oldCollection, scope)} listener a callback function called
   when a change is detected.
   - The `newCollection` object is the newly modified data obtained from the `obj` expression
   - The `oldCollection` object is a copy of the former collection data.
     Due to performance considerations, the`oldCollection` value is computed only if the
     `listener` function declares two or more arguments.
   - The `scope` argument refers to the current scope.

@returns {function()} Returns a de-registration function for this listener. When the
   de-registration function is executed, the internal watch operation is terminated.