https://docs.angularjs.org/guide/directive
Listeners registered to scopes and elements are automatically cleaned up when they are destroyed, but if you registered a listener on a service, or registered a listener on a DOM node that isn't being deleted, you'll have to clean it up yourself or you risk introducing a memory leak.
I don't understand one thing (actually I don't understand many things about Angular, but now I'm aimed exactly at this). Can anybody explain the difference between registered to scopes and elements" and "registered a listener on a service, or registered a listener on a DOM". What is the difference between elements and DOM in this sentence. And why in first case listeners are automatically cleaned up, but in second they aren't. What is being registered to elements and what is being registered on DOM?
Note we are speaking of two slightly different kinds of cleanup here:
In these cases Angular cleans up for you:
// Watching scope vars
$scope.$watch("scopeVariable", function (newVal) { ... });
$scope.$watch("injectedService.serviceVar", function (newVal) { ... } );
// Listening to events from a scope
$scope.$on("event", function () { ... });
// Events of the element of a directive,
// within the directive 'link' function (the docs you referenced)
element.on('click', function() { ... });
In all these cases, it's not necessary to do any cleanup. Angular knows that some code is listening to events or watching variables, and can unregister them. For the element, since it will be removed, all closures and related objects will be unreferenced, and thus later disposed by the garbage collector.
On the other hand, in the following cases Angular will not do cleanup for you:
// Listening to events from rootScope
$rootScope.$on("event", function () { ... });
// Subscribing to services events
someInjectedService.subscribeIncomingMessage(function () { ... });
// Adding elements outside directive container element
var body = $document.find('body').eq(0);
var newElement = angular.element('<div></div>');
body.append(newElement);
// Listening to events of elements outside your directive (ie. body)
body.on("click", function() { ... });
In these cases, Angular will never destroy your listeners, nor the created element added to the <body> of the document.
In raw words, I'd say Angular will just destroy everything inside your scope or contained in the DOM of your directive root element. Everything else you listen to, or elements that you create and place outside your directive, are your responsibility.
Quoting angular docs, you would do cleanup by listening to the destroy events:
Best Practice: Directives should clean up after themselves. You can use
element.on('$destroy', ...)orscope.$on('$destroy', ...)to run a clean-up function when the directive is removed.
I personally add these methods only when there's something to clean up. You need to do this especially if you create elements of register for external events (ie. messages coming from websockets, or scheduled timeout events), otherwise you risk ending up with several listeners for the same event (usually causing misbehavior and sluggishness).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With