In any program, a variable takes up some memory. In low-level programming languages such as C, the programmer must allocate and deallocate memory manually. In contrast, the V8 JavaScript engine and other modern JavaScript engines have garbage collectors that delete unused variables for the programmer. Despite this memory management done by the JavaScript engine, however, there are common pitfalls that developers can fall into. This chapter will show some basic examples of these pitfalls and present techniques to help the garbage collector minimize the key JavaScript memory problems.
Memory Leaks
A memory leak is a failure in a program to release discarded memory, causing impaired performance and sometimes even failure. Memory leaks can happen when JavaScript engines’ garbage collectors do not free memory properly.
Follow the key principles outlined in this chapter to avoid memory leaks during JavaScript development.
Reference to an Object
You might expect the clickEvent() function to use 5KB of memory since it is only referencing bar1 from the foo object. However, the truth is that it is using 10KB of memory since it has to load the whole foo object into the function’s into scope to access the bar1 property.
Leaking DOM
If a variable pointing to a DOM element is declared outside of an event callback, then it is in memory and leaks DOM if the element is deleted.
The event listener on the one element will cause the two to disappear from the web page when clicked. However, even if the DOM is deleted in the HTML, reference to it will remain if used in an event callback. When the two element is no longer in use, this is a memory leak and should be avoided.
Global window Object
If an object is on the global window object, it is in memory. The window object is a global object in a browser and comes with various built-in methods such as alert() and setTimeout(). Any additional objects declared as a property of window will not be cleared because window is a required object for the browser to run. Remember that any global variable declared will be set as a property of the window object.
It is good to avoid global variables whenever possible. This will help save memory.
Limiting Object References
An object is cleared when all references are cleared. Always remember to limit the amount of scope the function pulls and pass the property of an object only into functions instead of the entire object. This is because the object’s memory footprint can be very large (e.g., an array of 100,000 integers for data visualization project); if only one of the object’s properties is needed, you should avoid using the entire object as a parameter.
The delete Operator
Summary
Although memory in JavaScript is not allocated by the programmer, there are still numerous ways to mitigate memory leaks where applicable. If the object is in reference, it is in memory. Similarly, HTML DOM elements should not be referenced once deleted. Finally, only reference objects in a function that are needed. In many cases, it is more applicable to pass in a property of the object rather than the object itself. Also, be extremely mindful when declaring a global variable.
Exercises
In this chapter, exercises are about identifying memory inefficiencies and optimizing a given piece of code.
ANALYZING AND OPTIMIZING A PROPERTY CALL
Problem: An excessive amount of memory is used in printProperty because the entire object is brought into the printProperty function. To fix this, only the property being printed should be brought in as a parameter of the function.
ANALYZING AND OPTIMIZING SCOPE
Problem: Global variables are used where not necessary. Albeit small, the global variables RED, GREEN, and BLUE bloat the global scope and should be moved inside the redGreenBlueCount function.
ANALALYZING AND REPAIRING MEMORY ISSUES
Analyze and fix memory issues for the following code.
Problem: This is the “leaking DOM” issue discussed earlier in the chapter. When elements are removed, they are still referenced by the callback function. To address this, put the one and two variables into a callback’s scope and remove the event listener after.
Answer: