Memory leaks in AngularJS occur when references to objects persist even after they are no longer needed. This can degrade application performance over time. Below are the best practices to avoid memory leaks in AngularJS.
1. Use $scope.$destroy() When Removing DOM Elements
When a scope is no longer needed, manually destroy it using $destroy()
to prevent memory leaks.
Example:
$scope.$on("$destroy", function() {
console.log("Scope destroyed!");
});
This ensures that when a component or controller is removed, AngularJS cleans up the memory.
2. Unbind Event Listeners ($on)
If you use $scope.$on()
for event handling, always unbind it in the $destroy
method.
Example:
var eventListener = $scope.$on("customEvent", function(event, data) {
console.log("Event received:", data);
});
// Unbind when scope is destroyed
$scope.$on("$destroy", function() {
eventListener();
});
This prevents event handlers from accumulating and causing memory bloat.
3. Avoid Using jQuery Directly
If you must use jQuery, always clean up event listeners.
Bad Practice:
$(window).on("resize", function() {
console.log("Window resized");
});
Good Practice:
var resizeHandler = function() {
console.log("Window resized");
};
$(window).on("resize", resizeHandler);
$scope.$on("$destroy", function() {
$(window).off("resize", resizeHandler);
});
This ensures that the event listener is removed when the scope is destroyed.
4. Use One-Time Bindings (::
) Where Possible
If data doesn’t change frequently, use one-time binding to reduce watchers.
Example:
<p>{{::user.name}}</p>
This ensures AngularJS stops watching user.name
after the first evaluation, reducing memory usage.
5. Avoid Global Variables
Never store data globally, as it prevents garbage collection.
Bad Practice:
window.userList = [];
Good Practice:
Use $scope
or services for data management.
6. Remove DOM Elements Manually
If you dynamically create DOM elements, remove them when they are no longer needed.
Example:
var element = angular.element("<div>Test</div>");
angular.element(document.body).append(element);
$scope.$on("$destroy", function() {
element.remove();
});
7. Limit $watch
Usage
Too many $watch
statements slow down the digest cycle.
Bad Practice:
$scope.$watch("data", function(newValue, oldValue) {
console.log("Data changed");
});
Good Practice:
Use $watch
only when necessary or replace it with $watchCollection
.
$scope.$watchCollection("items", function(newItems) {
console.log("Items changed");
});
8. Optimize $timeout and $interval Usage
Always cancel $timeout
and $interval
when they are no longer needed.
Example:
var timer = $timeout(function() {
console.log("Task executed");
}, 5000);
$scope.$on("$destroy", function() {
$timeout.cancel(timer);
});
For $interval
, follow the same approach:
var interval = $interval(function() {
console.log("Repeating task");
}, 1000);
$scope.$on("$destroy", function() {
$interval.cancel(interval);
});
9. Clean Up Services
If a service holds persistent references, clean them up when they are no longer needed.
Example:
app.factory("DataService", function() {
var data = {};
return {
set: function(key, value) {
data[key] = value;
},
get: function(key) {
return data[key];
},
clear: function() {
data = {};
}
};
});
Call clear()
when the service is no longer needed.
10. Use ng-if Instead of ng-show/ng-hide
ng-show
and ng-hide
only toggle visibility, but ng-if
removes the element from the DOM, freeing memory.
Example:
<!-- Better than ng-show -->
<div ng-if="showElement">
<p>This element is added and removed dynamically.</p>
</div>