AshD
AshD

Reputation: 1156

Watching in scope vs parent scope for the same value change - is there a difference?

I have a pretty basic question about Angular watches. Say I have following in the link function of my directive:

scope.$watch(function(){
    return element.isVisible();
  }, myFuncUponVisibleChange);

Is this going to be the same as:

scope.$parent.$watch(function(){
     return element.isVisible();
  }, myFuncUponVisibleChange);

In other words, is Angular watching for the visibility of the same element in both cases above?

Upvotes: 1

Views: 49

Answers (2)

Estus Flask
Estus Flask

Reputation: 222369

Yes, both scope watchers watch on the same element, because element refers to particular object, and it was referenced in watcher function.

And yes, there is a substantial difference.

A lot of performance issues in AngularJS are caused by the fact that digest cycles affect the entire scope hierarchy. In other words, $scope.$apply() triggers all watchers from top to bottom.

Once the application is complex enough (it always depends on client and app, but the crucial point is often estimated at ~1000 watchers for simplicity), it starts to become unresponsive on digests.

A good way to optimize this is to encapsulate directive changes and keep directives from announcing digests on root scope, unless global digest is the desired behaviour. In this case $scope.$digest() may be called instead of $scope.$apply() (the fundamental difference between those two is that the latter calls $rootScope.$digest()).

Here comes the difference. scope.$parent.$watch(...) watcher won't be triggered on $scope.$digest() but it will be on $scope.$apply(). And it shows why directive isolation is important and why referring parent scope from child is bad habit.

Another unpleasant surprise is that scope.$parent.$watch(...) may cause memory leaks. If the element that owns scope was destroyed, the watcher won't be cleaned up automatically. And it will refer to detached element, preventing the object from being garbage-collected.

$scope.$parent is evil.

Upvotes: 1

arjabbar
arjabbar

Reputation: 6404

Yes it is. What $element is does not change because you are capturing the $element reference that you have in that scope (JavaScript scope, not Angular scope) when you are declaring that function.

Now if you did something like this:

scope.$parent.$watch('$element.isVisible()', myFuncUponVisibleChange);

Then that would be totally different, because at that point you would be referencing the $element from the parent scope, not the other scope.

Upvotes: 1

Related Questions