Memory leaks in JavaScript
JavaScript is a garbage-collected language, which means that memory is assigned to the object based on the creation of the object and is retracted by the browser when there is no reference to the object. The garbage collection mechanism of JavaScript itself is not a problem, but the way the browser allocates and recovers memory for DOM objects is somewhat out of the question.
Both Internet Explorer and Mozilla Firefox use reference counts 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 consumes is returned to the heap. While this solution is generally valid, there are some blind spots in circular referencing.
What is the problem with circular referencing?
When two objects reference each other, a circular reference is made, where the reference count value of each object is assigned 1. In a pure garbage collection system, there is little problem with circular referencing: if one of the two objects involved is referenced by any other object, both objects will be garbage collected. In the 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 occurs because the system does not correctly recognize the circular reference. In this case, both the DOM object and the JavaScript object cannot be destroyed. Listing 1 shows a circular reference that exists between the JavaScript object and the DOM object.
Listing 1. A circular reference causes a memory leak
As shown in the preceding list, the JavaScript object obj
has a reference to the DOM object, expressed as DivElement
. The DOM object is represented by a reference to this JavaScript object expandoProperty
. Visible, a circular reference is generated between the JavaScript object and the DOM object. Because DOM objects are managed by reference counting, none of the two objects will be destroyed.
Another memory leak mode
In Listing 2, you create a circular reference by calling an external function myFunction
. Similarly, a circular reference between a JavaScript object and a DOM object can cause a memory leak.
Listing 2. Memory leaks caused by external function calls
new MyFunction (document.getElementById ("mydiv"));} </script> |
As the two code examples show, circular references are easy to create. One of the most convenient programming constructs in JavaScript: in closures, circular references are particularly prominent.
Closures in JavaScript
The advantage of JavaScript is that it allows functions to be nested. A nested intrinsic function can inherit arguments and variables of an external function and is privately owned by the external function. Listing 3 shows an example of an intrinsic function.
Listing 3. An intrinsic function
function Parentfunction (Parama) { var a = Parama; function childfunction () {return a + 2; } return childfunction ();} |
JavaScript developers use intrinsic functions to integrate small utility functions into other functions. As shown in Listing 3, this intrinsic function childFunction
can access parentFunction
the variables of the external function. When an intrinsic function obtains and uses a variable of its outer function, it is called a closure .
Understanding closures
Consider the code snippet shown in Listing 4.
Listing 4. A simple closure
In the above list, the closureDemoInnerFunction
intrinsic function is defined in the parent function closureDemoParentFunction
. When called with an external x pair closureDemoParentFunction
, the external function variable a is assigned a value of external x . The function returns closureDemoInnerFunction
a pointer to an intrinsic function, which is included within the variable x .
closureDemoParentFunction
The local variable a of the external function will still exist even when the external function returns. This is different from a programming language such as C + +, where the local variable will no longer exist once the function returns. In JavaScript, closureDemoParentFunction
when called, a Range object with property a will be created. 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 an external function's variable, 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 very powerful because they enable internal functions to retain access to variables of this external function when the external function returns. Unfortunately, closures are very easy to hide a circular reference between a JavaScript object and a DOM object.
Closures and circular references
In Listing 5, you can see a closure in which the JavaScript object ( obj
) contains a reference to the DOM object (referenced by ID "element"
). The DOM element, however, has a reference to JavaScript obj
. A circular reference between the created JavaScript object and the DOM object will cause 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 patterns that can lead to circular references, as we did in the previous sections, you can begin to deal with these patterns. Here, we will show three ways to deal with known memory leaks, using the memory leak pattern caused by event handling as an example.
One solution to the memory leak in Listing 5 is to make this JavaScript object obj
empty, which explicitly breaks 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
(function anotherinnerfunction () {var obj = document.getElementById ("element"); Obj.onclick=anotherobj} )(); }; </script><button id= "Element" > "Click here" </button></body> |
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 herealert ("hi! I have avoided the leak ");} </script> |
Conclusion
This article explains how circular references can lead to memory leaks in JavaScript-especially in the case of a combination of closures. You also learned about some common memory leak patterns that involve circular references and several simple ways to deal with these leak patterns
Original address: http://wv1124.iteye.com/blog/524896
Memory leaks in JavaScript