admin管理员组

文章数量:1181439

I'm interested to find out why i always have to do this

$scope.$watch( function() {
   return $scope.someData;
}, function( value ) {
   console.log( value );
});

for angular to actually watch the data, why do I have to do this, this is one of the things that really bug me because it looks pointless.

If I do something like this

$scope.$watch($scope.someData, function( value ) {
   console.log( value );
});

Which is nicer, it never works?

I also use this a lot with factories

say that $data is a factory I have to do

$scope.$watch( function() {
   return $data.someData;
}, function( value ) {
   console.log( value );
});

I'm interested to find out why i always have to do this

$scope.$watch( function() {
   return $scope.someData;
}, function( value ) {
   console.log( value );
});

for angular to actually watch the data, why do I have to do this, this is one of the things that really bug me because it looks pointless.

If I do something like this

$scope.$watch($scope.someData, function( value ) {
   console.log( value );
});

Which is nicer, it never works?

I also use this a lot with factories

say that $data is a factory I have to do

$scope.$watch( function() {
   return $data.someData;
}, function( value ) {
   console.log( value );
});
Share Improve this question asked Aug 13, 2013 at 16:47 iConnoriConnor 20.2k14 gold badges65 silver badges97 bronze badges 1
  • 1 do: $scope.$watch('someData', function (... – Yoshi Commented Aug 13, 2013 at 16:49
Add a comment  | 

4 Answers 4

Reset to default 23

I guess it's worth mentioning that passing a function to $watch is useful when you want to monitor a condition:

$scope.$watch(function() { 
    return $scope.data.length > 0; 
}, function() {
    // Do something every time $scope.data.length > 0 changes
});

or

$scope.$watch(function() { 
    return $scope.prop1 && $scope.prop2;
}, function() {
    // Do something every time $scope.prop1 && $scope.prop2 changes
});

This works:

$scope.$watch("someData", function( value ) {
   console.log( value );
});

With a factory, you need to watch a function because if you pass a string, Angular will evaluate it as an expression against the $scope. Since $data.someData is not defined on your $scope, it won't work.

To elaborate on @Codezilla's comment, you could assign your factory data to some $scope property, and then watch that:

$scope.data = $data.someData;
$scope.$watch('data', function(newValue) { ... });

Since the how-to-do answer is already given, I'll try to explain you what goes on actually and why it didn't work the way you tried at first time.

First of all this code sure works,

$scope.$watch(function() {
   return $scope.someData;
}, function(value) {
   console.log(value);
});

But this is NOT the perfect way. To be more precise $watch injects the scope in the function, like this,

$scope.$watch(function(injectedScope) {
   return injectedScope.someData;
}, function(value) {
   console.log(value);
});

Previously it works because $scope and injectScope are one and the same thing.

Now as this article explains,

Since $scope is passed into the watch function, it means that we can watch any function that expects the scope as an argument and returns a value in response. A great example of this is $interpolate function.

So in your case, we can also make use of $interpolate as following:

$scope.$watch($interpolate("{{someData}}"), function(value) {
    ...
});

Now this is where we come to the short-hand method of using just a watch expression. $watch can also accept an expression, which actually is interpolated.

Thus by providing $scope.$watch("someData", ... ),

someData will be:

  1. interpolated as {{someData}}
  2. using the scope injected by $watch function

This is a nice, clean, readable, short-hand way of writing the expression instead of the actual function. But finally after all such compilations, it is ultimately the function which returns a value to watch.

本文标签: javascriptAngular watchreturning the item from functionStack Overflow