Author:
Abhijeet Bhattacharya (abhbhatt@in.ibm.com), System software engineer, IBM India
Kiran Shivarama Shivarama Sundar (kisundar@in.ibm.com), System software engineer, IBM India
May 28, 2007
If you know the cause of the memory leak, it should be fairly easy to prevent it from being appropriate in JavaScript. In this article, the author Kiran Sundar and Abhijeet Bhattacharya will take you through all the basics of circular references in JavaScript, and show you why they can cause problems in some browsers, especially if the closures are combined. After learning about the common memory leak patterns that you should be aware of, you'll also learn a lot about how to deal with these leaks.
JavaScript is a powerful scripting language used to add dynamic content to a Web page. It is especially useful for daily tasks such as validating passwords and creating dynamic menu components. JavaScript is easy to learn and easy to use, but it can easily cause memory leaks in some browsers. In this introductory article, we explain how leaks in JavaScript are caused, show common memory leak patterns, and describe how to deal with them.
Note This article assumes that you are already very familiar with using JavaScript and DOM elements to develop WEB applications. This article is especially suitable for developers who use JavaScript for Web application development, and for customers interested in creating Web applications, as well as for browser support and for people who are responsible for browser troubleshooting.
Memory leaks in JavaScript
JavaScript is a garbage collection language, which means that memory is assigned to an object based on its creation and is retracted by the browser when no reference to the object is made. JavaScript's garbage collection mechanism is not inherently problematic, but browsers are somewhat different in how memory is allocated and restored for DOM objects.
Both Internet Explorer and Mozilla Firefox use reference counting to handle memory for DOM objects. In the reference counting system, each referenced object retains a count to learn how many objects are referencing it. If the count is zero, the object is destroyed and the memory it occupies is returned to the heap. While this solution is generally effective, there are some blind spots in circular references.
What is the problem with circular references?
When two objects are referenced to each other, a circular reference is formed, where each object's reference count value is assigned 1. In a pure garbage collection system, circular references are not a problem: if one of the two objects involved is referenced by any other object, both objects will be garbage collected. In a reference counting system, neither of these objects can be destroyed because the reference count can never be zero. In a hybrid system that uses both garbage collection and reference counting, a leak will occur because the system does not recognize the circular reference correctly. In this case, both the DOM object and the JavaScript object cannot be destroyed. Listing 1 shows a circular reference that exists between a JavaScript object and a DOM object.
Listing 1. A circular reference caused a memory leak
As shown in the above list, the JavaScript object
obj
has a reference to a DOM object, expressed as
DivElement
。 The DOM object has a reference to this JavaScript object, which is
expandoProperty
Said. Visible, a circular reference is generated between the JavaScript object and the DOM object. Because DOM objects are managed by reference counting, two objects will not be destroyed.
Another memory leak mode
In Listing 2, you create a circular reference by calling an external function myFunction
. Similarly, circular references between JavaScript objects and DOM objects can also cause memory leaks.
Listing 2. Memory leaks caused by external function calls
new MyFunction (document.getElementById ("mydiv"));
}
</script>
|
As shown in the two code examples, circular references are easy to create. One of the most convenient programming architectures in JavaScript: in closures, circular references are particularly prominent.
Closures in JavaScript
What's extraordinary about JavaScript is that it allows functions to be nested. A nested intrinsic function can inherit the arguments and variables of the external function and be private by the external function. Listing 3 shows an example of an internal function.
Listing 3. An intrinsic function
function Parentfunction (Parama)
{
var a = Parama;
function childfunction ()
{return
a + 2;
}
return childfunction ();
} |
JavaScript developers use internal functions to integrate small utility functions into other functions. As shown in Listing 3, this internal function
childFunction
can access external functions
parentFunction
The variable. When an intrinsic function obtains and uses a variable of its external function, it is called a
Closed Bag。
Understanding closures
Consider the code snippet as shown in Listing 4.
Listing 4. A simple closure
In the above list,
closureDemoInnerFunction
is in the parent function
closureDemoParentFunction
The internal functions defined in the When using
the external xRight
closureDemoParentFunction
When making a call, the external function variable
aIt will be assigned the value of
the external x。 function returns a pointer to an internal function
closureDemoInnerFunction
The pointer that is included in the variable
xWithin
closureDemoParentFunction
The local variable a of the external function still exists even when the external function returns. This differs from a programming language such as C + +, in which the local variable ceases to exist once the function returns. In JavaScript, a closureDemoParentFunction
Range object with property a will be created when invoked. This property includes the value Parama, also known as the "external x". Similarly, when closureDemoParentFunction
returned, it returns an intrinsic function, which is closureDemoInnerFunction
included in the variable x .
Because an intrinsic function holds a reference to a variable of an external function, the Range object with attribute a will not be garbage collected. When a call is made to an x with a parameter value of inner x , a x("inner x")
warning message pops up indicating "outer x Innerx".
Listing 4 briefly explains the JavaScript closures. Closures are powerful because they enable internal functions to retain access to variables of this external function when they are returned by external functions. Unfortunately, closures are very easy to hide circular references between JavaScript objects and DOM objects.
Closures and circular references
In Listing 5, you can see a closure in which a JavaScript object ( obj
) contains a reference to a DOM object (referenced by ID "element"
). The DOM element has a reference to JavaScript obj
. This circular reference between JavaScript objects and DOM objects created by this will result in a memory leak.
Listing 5. Memory leak mode caused by event handling
Avoid memory leaks
Fortunately, memory leaks in JavaScript can be avoided. Once you have identified the patterns that can lead to circular references, as we have done in the previous sections, you can begin to deal with these patterns. Here, we will show you three ways to respond to known memory leaks with the example of the memory leak pattern caused by event handling .
One solution to the memory leak in Listing 5 is to have this JavaScript object obj
empty, which will explicitly break this circular reference, as shown in Listing 6.
listing 6. Breaking Circular references
obj = null;//this breaks the circular reference
};
</script>
<button id= "element" > "click here" </button>
</body>
|
Listing 7 avoids circular references between JavaScript objects and DOM objects by adding another closure.
Listing 7. Add another closure
Listing 8 prevents the leak by adding another function to avoid the closure itself.
Listing 8. Avoid closing the package itself
function Doesnotleak ()
{
//your Logic here
alert ("hi! I have avoided the leak ");
}
</script>
|
Concluding remarks
This article explains how circular references cause memory leaks in JavaScript-especially if the closures are combined. You also learned about some of the common memory leak patterns involved in circular references and several simple ways to respond to these leaks patterns.
Author Introduction
|
|
|
Abhijeet Bhattacharya is a system engineer at IBM India's software lab. He has been a member of the OS/2 IBM Web Browser Support team for the past three years. He also has experience in the field of system management and has participated in IBM Pegasus Open source Innovation project. The focus of his current work includes distributed computing and SARPC. He has a bachelor's degree in engineering from Rajiv Gandhi technical University. |
|
|
|
Kiran Shivarama Sundar is a system engineer at IBM India's software lab. He has been a member of the OS/2 IBM Web Browser Support team for the past three years. He also has experience with many other projects, including developing command line tools for Apache Tuscany Open Source Project and developing RFIDIC Installer for IBM's EPCIS team. Currently, Kiran has joined the IBM WebSphere adapters support Team, which is responsible for providing support for JMS and MQ adapters. He has successfully obtained the Sun Certified Java programmer, Sun certified Web Component Developer and Sun certified Business Component Certification. His current areas of interest include Java, EE, Web services, and SOA. He has a bachelor's degree in engineering from Visweshwaraya Technology University. |