When the structure "controllerAs" is used, the controller of añega to the scope with the name has been established here.
The most likely thing that is happening to you is what it says devconcept in one of the comments, that is, that at the time of declaring the name of the controller you are assigning a name other than vm
.
For example:
<div ng-controller="MyCtrl as viewModel">
Hello, {{viewModel.name}}!
</div>
function MyCtrl($scope) {
var vm = this;
vm.name = 'Superhero';
...
}
When using the structure "controllerAs" it is necessary to avoid doing the $scope.$watch
using an expression so as not to depend on the name that is assigned to the controller from the view.
The way to do it would be this:
$scope.$watch(function(scope){
return vm.name;
}, function(newValue, oldValue){
console.log('New name: ' + newValue);
});
You can see the complete example in this JSFiddle and in this article in English is explained in more detail.