AngularJS $watch vs. $watchCollection()

by Luis Perez

HTML

<div ng-app="MyModule" ng-controller="MyController">
</div>

JavaScript

var module = angular.module("MyModule", []);
module.controller("MyController", function($scope, $log, $timeout) {
    $scope.$watch("myArray", function() {
        $log.debug("    ** $watch()");
    });
    
    $scope.$watch("myArray", function() {
        $log.debug("    ** $watch(..., true)");
    }, true);
    
    $scope.$watchCollection("myArray", function() {
        $log.debug("    ** $watchCollection()");
    });
    
    $log.debug("So it begins...");
    
    setTimeout(function() {
        $log.debug("$scope.myArray = null // direct assignment");
        $scope.myArray = null;
        $scope.$digest();

        $log.debug("$scope.myArray = [] // direct assignment");
        $scope.myArray = [];
        $scope.$digest();

        $log.debug("$scope.myArray = [] // direct assignment again - same content");
        $scope.myArray = [];
        $scope.$digest();

        $log.debug("$scope.myArray.push({ name: 'John', skill: 'Wizard' }) // add element");
        $scope.myArray.push({ name: 'John', skill: 'Wizard' });
        $scope.$digest();
        
        $log.debug("$scope.myArray.push({ name: 'David', skill: 'Mage' }) // add element");
        $scope.myArray.push({ name: 'David', skill: 'Mage' });
        $scope.$digest();
        
        $log.debug("$scope.myArray.splice(0, 1) // remove element");
        $scope.myArray.splice(0, 1);
        $scope.$digest();
        
        $log.debug("$scope.myArray[0] = { name: 'Edgar', skill: 'Warrior' } // element assignment");
        $scope.myArray[0] = { name: 'Edgar', skill: 'Warrior' };
        $scope.$digest();

        $log.debug("$scope.myArray[0].skill = 'Software Developer' // assign element property");
        $scope.myArray[0].skill = 'Software Developer';
        $scope.$digest();
    });
    
    /*
    $timeout(function() {
        $log.debug("Assigned myArray to a new array instance");
        $scope.myArray = [];
        $scope.$apply();
        
    }, 100).then(function() {
        return...